Changeset 2833


Ignore:
Timestamp:
Aug 22, 2016, 11:00:38 PM (9 years ago)
Author:
bird
Message:

kWorker: More hacking.

Location:
trunk/src/kWorker
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kWorker/Makefile.kmk

    r2832 r2833  
    3434kWorker_TEMPLATE = BIN
    3535kWorker_INCS = kStuff/include
     36kWorker_DEFS.debug = K_STRICT
    3637kWorker_DEFS.release = NASSERT
    3738kWorker_SOURCES = kWorker.c
     
    5354LIBRARIES += kStuff
    5455kStuff_TEMPLATE = LIB
     56kStuff_DEFS.debug = K_STRICT
    5557kStuff_INCS = kStuff/include
    5658
  • trunk/src/kWorker/kWorker.c

    r2832 r2833  
    22/** @file
    33 * kWorker - experimental process reuse worker for Windows.
     4 *
     5 * Note! This module must be linked statically in order to avoid
     6 *       accidentally intercepting our own CRT calls.
    47 */
    58
     
    4043#include <Windows.h>
    4144#include <winternl.h>
     45
     46
     47/*********************************************************************************************************************************
     48*   Defined Constants And Macros                                                                                                 *
     49*********************************************************************************************************************************/
     50/** Special KWFSOBJ::uCacheGen number indicating that it does not apply. */
     51#define KFSWOBJ_CACHE_GEN_IGNORE        KU32_MAX
     52
     53/** String constant comma length.   */
     54#define TUPLE(a_sz)                     a_sz, sizeof(a_sz) - 1
     55
     56/** @def KW_LOG
     57 * Generic logging.
     58 * @param a     Argument list for kwDbgPrintf  */
     59#ifndef NDEBUG
     60# define KW_LOG(a) kwDbgPrintf a
     61#else
     62# define KW_LOG(a) do { } while (0)
     63#endif
     64
     65
     66/** @def KWFS_LOG
     67 * FS cache logging.
     68 * @param a     Argument list for kwDbgPrintf  */
     69#ifndef NDEBUG
     70# define KWFS_LOG(a) kwDbgPrintf a
     71#else
     72# define KWFS_LOG(a) do { } while (0)
     73#endif
    4274
    4375
     
    95127        {
    96128            /** The of the loaded image bits. */
    97             size_t              cbImage;
     129            KSIZE               cbImage;
    98130            /** Where we load the image. */
    99131            void               *pvLoad;
     
    106138            KWMODSTATE          enmState;
    107139            /** Number of imported modules. */
    108             size_t              cImpMods;
     140            KSIZE               cImpMods;
    109141            /** Import array (variable size). */
    110142            PKWMODULE           apImpMods[1];
     
    137169    PKWMODULE           pMod;
    138170} KWDYNLOAD;
     171
     172
     173typedef struct KWFSOBJ *PKWFSOBJ;
     174typedef struct KWFSOBJ
     175{
     176    /** The object name.  (Allocated after the structure.) */
     177    const char         *pszName;
     178    /** The UTF-16 object name.  (Allocated after the structure.) */
     179    const wchar_t      *pwszName;
     180    /** The length of pszName. */
     181    KU16                cchName;
     182    /** The length of UTF-16 (in wchar_t's). */
     183    KU16                cwcName;
     184
     185    /** The number of child objects. */
     186    KU32                cChildren;
     187    /** Child objects. */
     188    PKWFSOBJ           *papChildren;
     189    /** Pointer to the parent. */
     190    PKWFSOBJ            pParent;
     191
     192    /** The cache generation, KFSWOBJ_CACHE_GEN_IGNORE. */
     193    KU32                uCacheGen;
     194    /** The GetFileAttributes result for the file.
     195     * FILE_ATTRIBUTE_XXX or INVALID_FILE_ATTRIBUTES. */
     196    KU32                fAttribs;
     197    /** The GetLastError() for INVALI_FILE_ATTRIBUTES. */
     198    KU32                uLastError;
     199
     200    /** Cached file handle. */
     201    HANDLE              hCached;
     202    /** The file size. */
     203    KSIZE               cbCached;
     204    /** Cached file content. */
     205    KU8                *pbCached;
     206} KWFSOBJ;
     207
     208
     209/** Pointer to an ANSI path hash table entry. */
     210typedef struct KWFSHASHA *PKWFSHASHA;
     211/**
     212 * ANSI file system path hash table entry.
     213 * The path hash table allows us to skip parsing and walking a path.
     214 */
     215typedef struct KWFSHASHA
     216{
     217    /** Next entry with the same hash. */
     218    PKWFSHASHA          pNext;
     219    /** Path hash value. */
     220    KU32                uHashPath;
     221    /** The path length. */
     222    KU32                cchPath;
     223    /** The path.  (Allocated after the structure.) */
     224    const char         *pszPath;
     225    /** Pointer to the matching FS object. */
     226    PKWFSOBJ            pFsObj;
     227} KWFSHASHA;
     228
     229
     230/** Pointer to an UTF-16 path hash table entry. */
     231typedef struct KWFSHASHW *PKWFSHASHW;
     232/**
     233 * UTF-16 file system path hash table entry. The path hash table allows us
     234 * to skip parsing and walking a path.
     235 */
     236typedef struct KWFSHASHW
     237{
     238    /** Next entry with the same hash. */
     239    PKWFSHASHW          pNext;
     240    /** Path hash value. */
     241    KU32                uHashPath;
     242    /** The path length (in wchar_t units). */
     243    KU32                cwcPath;
     244    /** The path.  (Allocated after the structure.) */
     245    const wchar_t      *pwszPath;
     246    /** Pointer to the matching FS object. */
     247    PKWFSOBJ            pFsObj;
     248} KWFSHASHW;
    139249
    140250
     
    263373static PKWTOOL      g_apTools[63];
    264374
     375/** Special file system root (parent to the drive letters). */
     376static KWFSOBJ      g_FsRoot =
     377{
     378    /* .pszName     = */ "",
     379    /* .pwszName    = */ L"",
     380    /* .cchName     = */ 0,
     381    /* .cwcName     = */ 0,
     382    /* .cChildren   = */ 0,
     383    /* .papChildren = */ NULL,
     384    /* .pParent     = */ NULL,
     385    /* .uCacheGen   = */ KFSWOBJ_CACHE_GEN_IGNORE,
     386    /* .fAttribs    = */ FILE_ATTRIBUTE_DIRECTORY,
     387    /* .uLastError  = */ ERROR_PATH_NOT_FOUND,
     388    /* .hCached     = */ INVALID_HANDLE_VALUE,
     389    /* .cbCached    = */ 0,
     390    /* .pbCached    = */ NULL,
     391};
     392/** File system hash table for ANSI filename strings. */
     393static PKWFSHASHA   g_apFsAnsiPaths[1021];
     394/** File system hash table for UTF-16 filename strings. */
     395static PKWFSHASHW   g_apFsUtf16Paths[1021];
     396/** Special file system object returned if the path is invalid. */
     397static KWFSOBJ      g_FsPathNotFound =
     398{
     399    /* .pszName     = */ "",
     400    /* .pwszName    = */ L"",
     401    /* .cchName     = */ 0,
     402    /* .cwcName     = */ 0,
     403    /* .cChildren   = */ 0,
     404    /* .papChildren = */ NULL,
     405    /* .pParent     = */ NULL,
     406    /* .uCacheGen   = */ KFSWOBJ_CACHE_GEN_IGNORE,
     407    /* .fAttribs    = */ FILE_ATTRIBUTE_DIRECTORY,
     408    /* .uLastError  = */ ERROR_PATH_NOT_FOUND,
     409    /* .hCached     = */ INVALID_HANDLE_VALUE,
     410    /* .cbCached    = */ 0,
     411    /* .pbCached    = */ NULL,
     412};
     413/** The cache generation number, incremented for each sandboxed execution.
     414 * This is used to invalid negative results from parts of the file system. */
     415static KU32         g_uFsCacheGeneration = 0;
     416
     417/** Verbosity level. */
    265418static int          g_cVerbose = 2;
    266419
     
    268421extern KWREPLACEMENTFUNCTION const g_aSandboxReplacements[];
    269422extern KU32                  const g_cSandboxReplacements;
     423
     424extern KWREPLACEMENTFUNCTION const g_aSandboxNativeReplacements[];
     425extern KU32                  const g_cSandboxNativeReplacements;
    270426
    271427/** Create a larget BSS blob that with help of /IMAGEBASE:0x10000 should
     
    282438static FNKLDRMODGETIMPORT kwLdrModuleGetImportCallback;
    283439static int kwLdrModuleResolveAndLookup(const char *pszName, PKWMODULE pExe, PKWMODULE pImporter, PKWMODULE *ppMod);
     440static PKWFSOBJ kwFsLookupA(const char *pszPath);
    284441
    285442
     
    294451    if (g_cVerbose >= 2)
    295452    {
     453        DWORD const dwSavedErr = GetLastError();
     454
    296455        fprintf(stderr, "debug: ");
    297456        vfprintf(stderr, pszFormat, va);
     457
     458        SetLastError(dwSavedErr);
    298459    }
    299460}
     
    326487    if (IsDebuggerPresent())
    327488    {
     489        DWORD const dwSavedErr = GetLastError();
    328490        char szTmp[2048];
     491
    329492        _vsnprintf(szTmp, sizeof(szTmp), pszFormat, va);
    330493        OutputDebugStringA(szTmp);
     494
     495        SetLastError(dwSavedErr);
    331496    }
    332497}
     
    355520static void kwErrPrintfV(const char *pszFormat, va_list va)
    356521{
     522    DWORD const dwSavedErr = GetLastError();
     523
    357524    fprintf(stderr, "error: ");
    358525    vfprintf(stderr, pszFormat, va);
     526
     527    SetLastError(dwSavedErr);
    359528}
    360529
     
    374543
    375544
     545#ifdef K_STRICT
     546
     547KHLP_DECL(void) kHlpAssertMsg1(const char *pszExpr, const char *pszFile, unsigned iLine, const char *pszFunction)
     548{
     549    DWORD const dwSavedErr = GetLastError();
     550
     551    fprintf(stderr,
     552            "\n"
     553            "!!Assertion failed!!\n"
     554            "Expression: %s\n"
     555            "Function :  %s\n"
     556            "File:       %s\n"
     557            "Line:       %d\n"
     558            ,  pszExpr, pszFunction, pszFile, iLine);
     559
     560    SetLastError(dwSavedErr);
     561}
     562
     563
     564KHLP_DECL(void) kHlpAssertMsg2(const char *pszFormat, ...)
     565{
     566    DWORD const dwSavedErr = GetLastError();
     567    va_list va;
     568
     569    va_start(va, pszFormat);
     570    fprintf(stderr, pszFormat, va);
     571    va_end(va);
     572
     573    SetLastError(dwSavedErr);
     574}
     575
     576#endif /* K_STRICT */
     577
     578
    376579/**
    377580 * Normalizes the path so we get a consistent hash.
     
    382585 * @param   cbNormPath          The size of the output buffer.
    383586 */
    384 static int kwPathNormalize(const char *pszPath, char *pszNormPath, size_t cbNormPath)
     587static int kwPathNormalize(const char *pszPath, char *pszNormPath, KSIZE cbNormPath)
    385588{
    386589    char *pchSlash;
     
    424627
    425628
     629/**
     630 * Hashes a string.
     631 *
     632 * @returns The string length.
     633 * @param   pszString           String to hash.
     634 * @param   puHash              Where to return the 32-bit string hash.
     635 */
     636static KSIZE kwStrHashEx(const char *pszString, KU32 *puHash)
     637{
     638    const char * const pszStart = pszString;
     639    KU32 uHash = 0;
     640    KU32 uChar;
     641    while ((uChar = (unsigned char)*pszString) != 0)
     642    {
     643        uHash = uChar + (uHash << 6) + (uHash << 16) - uHash;
     644        pszString++;
     645    }
     646    *puHash = uHash;
     647    return pszString - pszStart;
     648}
     649
     650
     651/**
     652 * Hashes a string.
     653 *
     654 * @returns The string length in wchar_t units.
     655 * @param   pwszString          String to hash.
     656 * @param   puHash              Where to return the 32-bit string hash.
     657 */
     658static KSIZE kwUtf16HashEx(const wchar_t *pwszString, KU32 *puHash)
     659{
     660    const wchar_t * const pwszStart = pwszString;
     661    KU32 uHash = 0;
     662    KU32 uChar;
     663    while ((uChar = *pwszString) != 0)
     664    {
     665        uHash = uChar + (uHash << 6) + (uHash << 16) - uHash;
     666        pwszString++;
     667    }
     668    *puHash = uHash;
     669    return pwszString - pwszStart;
     670}
     671
    426672
    427673/**
     
    433679 * @param   cwcDst              The size of the destination buffer in wchar_t's.
    434680 */
    435 static size_t kwStrToUtf16(const char *pszSrc, wchar_t *pwszDst, size_t cwcDst)
     681static KSIZE kwStrToUtf16(const char *pszSrc, wchar_t *pwszDst, KSIZE cwcDst)
    436682{
    437683    /* Just to the quick ASCII stuff for now. correct ansi code page stuff later some time.  */
    438     size_t offDst = 0;
     684    KSIZE offDst = 0;
    439685    while (offDst < cwcDst)
    440686    {
     
    459705 * @param   cbDst               The size of the destination buffer in bytes.
    460706 */
    461 static size_t kwUtf16ToStr(const wchar_t *pwszSrc, char *pszDst, size_t cbDst)
     707static KSIZE kwUtf16ToStr(const wchar_t *pwszSrc, char *pszDst, KSIZE cbDst)
    462708{
    463709    /* Just to the quick ASCII stuff for now. correct ansi code page stuff later some time.  */
    464     size_t offDst = 0;
     710    KSIZE offDst = 0;
    465711    while (offDst < cbDst)
    466712    {
     
    500746    if (cwcDst > 0)
    501747    {
    502         size_t cwcDstTmp = cwcDst - 1;
     748        KSIZE cwcDstTmp = cwcDst - 1;
    503749        pwszDst[cwcDstTmp] = '\0';
    504750        if (cwcDstTmp > 0)
     
    523769    if (cbDst > 0)
    524770    {
    525         size_t cbDstTmp = cbDst - 1;
     771        KSIZE cbDstTmp = cbDst - 1;
    526772        pszDst[cbDstTmp] = '\0';
    527773        if (cbDstTmp > 0)
     
    621867
    622868/**
     869 * Replaces imports for this module according to g_aSandboxNativeReplacements.
     870 *
     871 * @param   pMod                The natively loaded module to process.
     872 */
     873static void kwLdrModuleDoNativeImportReplacements(PKWMODULE pMod)
     874{
     875    KSIZE const                 cbImage = kLdrModSize(pMod->pLdrMod);
     876    KU8 const * const           pbImage = (KU8 const *)pMod->hOurMod;
     877    IMAGE_DOS_HEADER const     *pMzHdr  = (IMAGE_DOS_HEADER const *)pbImage;
     878    IMAGE_NT_HEADERS const     *pNtHdrs;
     879    IMAGE_DATA_DIRECTORY const *pDirEnt;
     880
     881    kHlpAssert(pMod->fNative);
     882
     883    /*
     884     * Locate the export descriptors.
     885     */
     886    /* MZ header. */
     887    if (pMzHdr->e_magic == IMAGE_DOS_SIGNATURE)
     888    {
     889        kHlpAssertReturnVoid(pMzHdr->e_lfanew <= cbImage - sizeof(*pNtHdrs));
     890        pNtHdrs = (IMAGE_NT_HEADERS const *)&pbImage[pMzHdr->e_lfanew];
     891    }
     892    else
     893        pNtHdrs = (IMAGE_NT_HEADERS const *)pbImage;
     894
     895    /* Check PE header. */
     896    kHlpAssertReturnVoid(pNtHdrs->Signature == IMAGE_NT_SIGNATURE);
     897    kHlpAssertReturnVoid(pNtHdrs->FileHeader.SizeOfOptionalHeader == sizeof(pNtHdrs->OptionalHeader));
     898
     899    /* Locate the import descriptor array. */
     900    pDirEnt = (IMAGE_DATA_DIRECTORY const *)&pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
     901    if (   pDirEnt->Size > 0
     902        && pDirEnt->VirtualAddress != 0)
     903    {
     904        const IMAGE_IMPORT_DESCRIPTOR  *pImpDesc    = (const IMAGE_IMPORT_DESCRIPTOR *)&pbImage[pDirEnt->VirtualAddress];
     905        KU32                            cLeft       = pDirEnt->Size / sizeof(*pImpDesc);
     906        MEMORY_BASIC_INFORMATION        ProtInfo    = { NULL, NULL, 0, 0, 0, 0, 0 };
     907        KU8                            *pbProtRange = NULL;
     908        SIZE_T                          cbProtRange = 0;
     909        DWORD                           fOldProt    = 0;
     910        KU32 const                      cbPage      = 0x1000;
     911        BOOL                            fRc;
     912
     913
     914        kHlpAssertReturnVoid(pDirEnt->VirtualAddress < cbImage);
     915        kHlpAssertReturnVoid(pDirEnt->Size < cbImage);
     916        kHlpAssertReturnVoid(pDirEnt->VirtualAddress + pDirEnt->Size <= cbImage);
     917
     918        /*
     919         * Walk the import descriptor array.
     920         * Note! This only works if there's a backup thunk array, otherwise we cannot get at the name.
     921         */
     922        while (   cLeft-- > 0
     923               && pImpDesc->Name > 0
     924               && pImpDesc->FirstThunk > 0)
     925        {
     926            KU32                iThunk;
     927            const char * const  pszImport   = (const char *)&pbImage[pImpDesc->Name];
     928            PIMAGE_THUNK_DATA   paThunks    = (PIMAGE_THUNK_DATA)&pbImage[pImpDesc->FirstThunk];
     929            PIMAGE_THUNK_DATA   paOrgThunks = (PIMAGE_THUNK_DATA)&pbImage[pImpDesc->OriginalFirstThunk];
     930            kHlpAssertReturnVoid(pImpDesc->Name < cbImage);
     931            kHlpAssertReturnVoid(pImpDesc->FirstThunk < cbImage);
     932            kHlpAssertReturnVoid(pImpDesc->OriginalFirstThunk < cbImage);
     933            kHlpAssertReturnVoid(pImpDesc->OriginalFirstThunk != pImpDesc->FirstThunk);
     934            kHlpAssertReturnVoid(pImpDesc->OriginalFirstThunk);
     935
     936            /* Iterate the thunks. */
     937            for (iThunk = 0; paOrgThunks[iThunk].u1.Ordinal != 0; iThunk++)
     938            {
     939                KUPTR const off = paOrgThunks[iThunk].u1.Function;
     940                kHlpAssertReturnVoid(off < cbImage);
     941                if (!IMAGE_SNAP_BY_ORDINAL(off))
     942                {
     943                    IMAGE_IMPORT_BY_NAME const *pName     = (IMAGE_IMPORT_BY_NAME const *)&pbImage[off];
     944                    KSIZE const                 cchSymbol = kHlpStrLen(pName->Name);
     945                    KU32                        i         = g_cSandboxNativeReplacements;
     946                    while (i-- > 0)
     947                        if (   g_aSandboxNativeReplacements[i].cchFunction == cchSymbol
     948                            && kHlpMemComp(g_aSandboxNativeReplacements[i].pszFunction, pName->Name, cchSymbol) == 0)
     949                        {
     950                            if (   !g_aSandboxNativeReplacements[i].pszModule
     951                                || kHlpStrICompAscii(g_aSandboxNativeReplacements[i].pszModule, pszImport) == 0)
     952                            {
     953                                KW_LOG(("%s: replacing %s!%s\n", pMod->pLdrMod->pszName, pszImport, pName->Name));
     954
     955                                /* The .rdata section is normally read-only, so we need to make it writable first. */
     956                                if ((KUPTR)&paThunks[iThunk] - (KUPTR)pbProtRange >= cbPage)
     957                                {
     958                                    /* Restore previous .rdata page. */
     959                                    if (fOldProt)
     960                                    {
     961                                        fRc = VirtualProtect(pbProtRange, cbProtRange, fOldProt, NULL /*pfOldProt*/);
     962                                        kHlpAssert(fRc);
     963                                        fOldProt = 0;
     964                                    }
     965
     966                                    /* Query attributes for the current .rdata page. */
     967                                    pbProtRange = (KU8 *)((KUPTR)&paThunks[iThunk] & ~(KUPTR)(cbPage - 1));
     968                                    cbProtRange = VirtualQuery(pbProtRange, &ProtInfo, sizeof(ProtInfo));
     969                                    kHlpAssert(cbProtRange);
     970                                    if (cbProtRange)
     971                                    {
     972                                        switch (ProtInfo.Protect)
     973                                        {
     974                                            case PAGE_READWRITE:
     975                                            case PAGE_WRITECOPY:
     976                                            case PAGE_EXECUTE_READWRITE:
     977                                            case PAGE_EXECUTE_WRITECOPY:
     978                                                /* Already writable, nothing to do. */
     979                                                break;
     980
     981                                            default:
     982                                                kHlpAssertMsgFailed(("%#x\n", ProtInfo.Protect));
     983                                            case PAGE_READONLY:
     984                                                cbProtRange = cbPage;
     985                                                fRc = VirtualProtect(pbProtRange, cbProtRange, PAGE_READWRITE, &fOldProt);
     986                                                break;
     987
     988                                            case PAGE_EXECUTE:
     989                                            case PAGE_EXECUTE_READ:
     990                                                cbProtRange = cbPage;
     991                                                fRc = VirtualProtect(pbProtRange, cbProtRange, PAGE_EXECUTE_READWRITE, &fOldProt);
     992                                                break;
     993                                        }
     994                                        kHlpAssertStmt(fRc, fOldProt = 0);
     995                                    }
     996                                }
     997
     998                                paThunks[iThunk].u1.AddressOfData = g_aSandboxNativeReplacements[i].pfnReplacement;
     999                                break;
     1000                            }
     1001                        }
     1002                }
     1003            }
     1004
     1005
     1006            /* Next import descriptor. */
     1007            pImpDesc++;
     1008        }
     1009
     1010
     1011        if (fOldProt)
     1012        {
     1013            DWORD fIgnore = 0;
     1014            fRc = VirtualProtect(pbProtRange, cbProtRange, fOldProt, &fIgnore);
     1015            kHlpAssertMsg(fRc, ("%u\n", GetLastError())); K_NOREF(fRc);
     1016        }
     1017    }
     1018
     1019}
     1020
     1021
     1022/**
    6231023 * Creates a module using the native loader.
    6241024 *
     
    6261026 * @param   pszPath             The normalized path to the module.
    6271027 * @param   uHashPath           The module path hash.
    628  */
    629 static PKWMODULE kwLdrModuleCreateNative(const char *pszPath, KU32 uHashPath)
     1028 * @param   fDoReplacements     Whether to do import replacements on this
     1029 *                              module.
     1030 */
     1031static PKWMODULE kwLdrModuleCreateNative(const char *pszPath, KU32 uHashPath, KBOOL fDoReplacements)
    6301032{
    6311033    /*
     
    6531055            pMod->pLdrMod       = pLdrMod;
    6541056            pMod->hOurMod       = (HMODULE)(KUPTR)pLdrMod->aSegments[0].MapAddress;
    655             kwDbgPrintf("New module: %p LB %#010x %s (native)\n",
    656                         (KUPTR)pMod->pLdrMod->aSegments[0].MapAddress, kLdrModSize(pMod->pLdrMod), pMod->pszPath);
     1057
     1058            if (fDoReplacements)
     1059            {
     1060                DWORD const dwSavedErr = GetLastError();
     1061                kwLdrModuleDoNativeImportReplacements(pMod);
     1062                SetLastError(dwSavedErr);
     1063            }
     1064
     1065            KW_LOG(("New module: %p LB %#010x %s (native)\n",
     1066                    (KUPTR)pMod->pLdrMod->aSegments[0].MapAddress, kLdrModSize(pMod->pLdrMod), pMod->pszPath));
    6571067            return kwLdrModuleLink(pMod);
    6581068        }
     
    7571167                            if (!fExe)
    7581168                                kwLdrModuleLink(pMod);
    759                             kwDbgPrintf("New module: %p LB %#010x %s (kLdr)\n",
    760                                         pMod->u.Manual.pvLoad, pMod->u.Manual.cbImage, pMod->pszPath);
     1169                            KW_LOG(("New module: %p LB %#010x %s (kLdr)\n",
     1170                                    pMod->u.Manual.pvLoad, pMod->u.Manual.cbImage, pMod->pszPath));
    7611171                            kwDebuggerPrintf("TODO: .reload /f %s=%p\n", pMod->pszPath, pMod->u.Manual.pvLoad);
    7621172
     
    8381248                    || kHlpStrICompAscii(g_aSandboxReplacements[i].pszModule, &pImpMod->pszPath[pImpMod->offFilename]) == 0)
    8391249                {
    840                     kwDbgPrintf("replacing %s!%s\n", &pImpMod->pszPath[pImpMod->offFilename], g_aSandboxReplacements[i].pszFunction);
     1250                    KW_LOG(("replacing %s!%s\n", &pImpMod->pszPath[pImpMod->offFilename], g_aSandboxReplacements[i].pszFunction));
    8411251                    *puValue = g_aSandboxReplacements[i].pfnReplacement;
     1252                    break;
    8421253                }
    8431254            }
     
    8701281
    8711282
     1283/**
     1284 * Whether to apply g_aSandboxNativeReplacements to the imports of this module.
     1285 *
     1286 * @returns K_TRUE/K_FALSE.
     1287 * @param   pszFilename         The filename (no path).
     1288 * @param   enmLocation         The location.
     1289 */
     1290static KBOOL kwLdrModuleShouldDoNativeReplacements(const char *pszFilename, KWLOCATION enmLocation)
     1291{
     1292    if (enmLocation != KWLOCATION_SYSTEM32)
     1293        return K_TRUE;
     1294    return kHlpStrNICompAscii(pszFilename, TUPLE("msvc"))   == 0
     1295        || kHlpStrNICompAscii(pszFilename, TUPLE("msdis"))  == 0
     1296        || kHlpStrNICompAscii(pszFilename, TUPLE("mspdb"))  == 0;
     1297}
     1298
     1299
     1300/**
     1301 * Whether we can load this DLL natively or not.
     1302 *
     1303 * @returns K_TRUE/K_FALSE.
     1304 * @param   pszFilename         The filename (no path).
     1305 * @param   enmLocation         The location.
     1306 */
    8721307static KBOOL kwLdrModuleCanLoadNatively(const char *pszFilename, KWLOCATION enmLocation)
    8731308{
     
    8761311    if (enmLocation == KWLOCATION_UNKNOWN_NATIVE)
    8771312        return K_TRUE;
    878     return kHlpStrICompAscii(pszFilename, "msvcrt.dll") == 0
    879         || kHlpStrNICompAscii(pszFilename, "msvc", 4)   == 0
    880         || kHlpStrNICompAscii(pszFilename, "msdis", 5)  == 0
    881         || kHlpStrNICompAscii(pszFilename, "mspdb", 5)  == 0;
     1313    return kHlpStrNICompAscii(pszFilename, TUPLE("msvc"))   == 0
     1314        || kHlpStrNICompAscii(pszFilename, TUPLE("msdis"))  == 0
     1315        || kHlpStrNICompAscii(pszFilename, TUPLE("mspdb"))  == 0;
    8821316}
    8831317
     
    9151349            if (rc == 0)
    9161350            {
    917                 KU32 const uHashPath = kwStrHash(szNormPath);
    918                 unsigned   idxHash   = uHashPath % K_ELEMENTS(g_apModules);
    919                 PKWMODULE  pMod      = g_apModules[idxHash];
     1351                const char *pszName;
     1352                KU32 const  uHashPath = kwStrHash(szNormPath);
     1353                unsigned    idxHash   = uHashPath % K_ELEMENTS(g_apModules);
     1354                PKWMODULE   pMod      = g_apModules[idxHash];
    9201355                if (pMod)
    9211356                {
     
    9321367                 * Not in the hash table, so we have to load it from scratch.
    9331368                 */
    934                 if (kwLdrModuleCanLoadNatively(kHlpGetFilename(szNormPath), enmLocation))
    935                     pMod = kwLdrModuleCreateNative(szNormPath, uHashPath);
     1369                pszName = kHlpGetFilename(szNormPath);
     1370                if (kwLdrModuleCanLoadNatively(pszName, enmLocation))
     1371                    pMod = kwLdrModuleCreateNative(szNormPath, uHashPath,
     1372                                                   kwLdrModuleShouldDoNativeReplacements(pszName, enmLocation));
    9361373                else
    9371374                    pMod = kwLdrModuleCreateNonNative(szNormPath, uHashPath, K_FALSE /*fExe*/, pExeMod);
     
    11251562    return NULL;
    11261563}
     1564
     1565
     1566
     1567/*
     1568 *
     1569 * File system cache.
     1570 * File system cache.
     1571 * File system cache.
     1572 *
     1573 */
     1574
     1575
     1576#define IS_ALPHA(ch) ( ((ch) >= 'A' && (ch) <= 'Z') || ((ch) >= 'a' && (ch) <= 'z') )
     1577#define IS_SLASH(ch) ((ch) == '\\' || (ch) == '/')
     1578
     1579
     1580/**
     1581 * Helper for getting the extension of a UTF-16 path.
     1582 *
     1583 * @returns Pointer to the extension or the terminator.
     1584 * @param   pwszPath        The path.
     1585 * @param   pcwcExt         Where to return the length of the extension.
     1586 */
     1587static wchar_t const *kwFsPathGetExtW(wchar_t const *pwszPath, KSIZE *pcwcExt)
     1588{
     1589    wchar_t const *pwszName = pwszPath;
     1590    wchar_t const *pwszExt  = NULL;
     1591    for (;;)
     1592    {
     1593        wchar_t const wc = *pwszPath++;
     1594        if (wc == '.')
     1595            pwszExt = pwszPath;
     1596        else if (wc == '/' || wc == '\\' || wc == ':')
     1597        {
     1598            pwszName = pwszPath;
     1599            pwszExt = NULL;
     1600        }
     1601        else if (wc == '\0')
     1602        {
     1603            if (pwszExt)
     1604            {
     1605                *pcwcExt = pwszPath - pwszExt - 1;
     1606                return pwszExt;
     1607            }
     1608            *pcwcExt = 0;
     1609            return pwszPath - 1;
     1610        }
     1611    }
     1612}
     1613
     1614
     1615/**
     1616 * Looks for '..' in the path.
     1617 *
     1618 * @returns K_TRUE if '..' component found, K_FALSE if not.
     1619 * @param   pszPath             The path.
     1620 * @param   cchPath             The length of the path.
     1621 */
     1622static KBOOL kwFsHasDotDot(const char *pszPath, KSIZE cchPath)
     1623{
     1624    const char *pchDot = (const char *)kHlpMemChr(pszPath, '.', cchPath);
     1625    while (pchDot)
     1626    {
     1627        if (pchDot[1] != '.')
     1628            pchDot = (const char *)kHlpMemChr(pchDot + 1, '.', &pszPath[cchPath] - pchDot - 1);
     1629        else
     1630        {
     1631            char ch;
     1632            if (   (ch = pchDot[2]) == '\0'
     1633                && IS_SLASH(ch))
     1634            {
     1635                if (pchDot == pszPath)
     1636                    return K_TRUE;
     1637                ch = pchDot[-1];
     1638                if (   IS_SLASH(ch)
     1639                    || ch == ':')
     1640                    return K_TRUE;
     1641            }
     1642            pchDot = (const char *)kHlpMemChr(pchDot + 2, '.', &pszPath[cchPath] - pchDot - 2);
     1643        }
     1644    }
     1645
     1646    return K_FALSE;
     1647}
     1648
     1649
     1650static void kwFsCreateHashTabEntryA(PKWFSOBJ pFsObj, const char *pszPath, KU32 cchPath, KU32 uHashPath, KU32 idxHashTab)
     1651{
     1652    PKWFSHASHA pHashEntry = (PKWFSHASHA)kHlpAlloc(sizeof(*pHashEntry) + cchPath + 1);
     1653    if (pHashEntry)
     1654    {
     1655        pHashEntry->uHashPath   = uHashPath;
     1656        pHashEntry->cchPath     = cchPath;
     1657        pHashEntry->pszPath     = (const char *)kHlpMemCopy(pHashEntry + 1, pszPath, cchPath + 1);
     1658        pHashEntry->pFsObj      = pFsObj;
     1659
     1660        pHashEntry->pNext = g_apFsAnsiPaths[idxHashTab];
     1661        g_apFsAnsiPaths[idxHashTab] = pHashEntry;
     1662    }
     1663}
     1664
     1665
     1666/**
     1667 * Refreshes a node that hash expired.
     1668 *
     1669 * This is for files and directories in the output directory tree.  The plan is
     1670 * to invalid negative results for each tool execution, in case a include file
     1671 * or directory has been created since the last time we were active.  Assuming
     1672 * that we'll be stopped together with kmk, there is no need to invalidate
     1673 * positive results.
     1674 *
     1675 * @param   pNode               The FS node.
     1676 */
     1677static void kwFsRefreshNode(PKWFSOBJ pNode)
     1678{
     1679    /** @todo implement once we've start inserting uCacheGen nodes. */
     1680    __debugbreak();
     1681}
     1682
     1683
     1684/**
     1685 * Links the child in under the parent.
     1686 *
     1687 * @returns K_TRUE on success, K_FALSE if out of memory.
     1688 * @param   pParent             The parent node.
     1689 * @param   pChild              The child node.
     1690 */
     1691static KBOOL kwFsLinkChild(PKWFSOBJ pParent, PKWFSOBJ pChild)
     1692{
     1693    if ((pParent->cChildren % 16) == 0)
     1694    {
     1695        void *pvNew = kHlpRealloc(pParent->papChildren, (pParent->cChildren + 16) * sizeof(pParent->papChildren[0]));
     1696        if (!pvNew)
     1697            return K_FALSE;
     1698        pParent->papChildren = (PKWFSOBJ *)pvNew;
     1699    }
     1700    pParent->papChildren[pParent->cChildren++] = pChild;
     1701    return K_TRUE;
     1702}
     1703
     1704
     1705/**
     1706 * Creates a child node for an ANSI path.
     1707 *
     1708 * @returns Pointer to the child tree node on success.
     1709 *          NULL on failure (out of memory).
     1710 * @param   pParent             The parent node.
     1711 * @param   pchPath             The path.
     1712 * @param   offName             The offset of the child name into pchPath.
     1713 * @param   cchName             The length of the child name.
     1714 */
     1715static PKWFSOBJ kwFsCreateChildA(PKWFSOBJ pParent, const char *pchPath, KU32 offName, KU32 cchName)
     1716{
     1717    char        szTmp[2048];
     1718    DWORD const dwSavedErr = GetLastError();
     1719    DWORD       dwAttr;
     1720    DWORD       dwErr;
     1721    PKWFSOBJ    pChild;
     1722
     1723    /*
     1724     * Get attributes.
     1725     */
     1726    if (pchPath[offName + cchName])
     1727    {
     1728        if (cchName + offName >= sizeof(szTmp))
     1729            return NULL;
     1730        memcpy(szTmp, pchPath, offName + cchName);
     1731        if (offName != 0 || cchName != 2 || pchPath[1] != ':')
     1732            szTmp[offName + cchName] = '\0';
     1733        else
     1734        {
     1735            /* Change 'E:' to 'E:\\.' so that it's actually absolute. */
     1736            szTmp[2] = '\\';
     1737            szTmp[3] = '.';
     1738            szTmp[4] = '\0';
     1739        }
     1740        pchPath = szTmp;
     1741    }
     1742
     1743    SetLastError(NO_ERROR);
     1744    dwAttr = GetFileAttributesA(pchPath);
     1745    dwErr  = GetLastError();
     1746
     1747    /*
     1748     * Create the entry.
     1749     */
     1750    pChild = (PKWFSOBJ)kHlpAlloc(sizeof(*pChild) + cchName + 1 + (cchName + 1) * sizeof(wchar_t) * 2);
     1751    SetLastError(dwSavedErr);
     1752    if (pChild)
     1753    {
     1754        pChild->pwszName    = (const wchar_t *)(pChild + 1);
     1755        pChild->pszName     = (const char *)kHlpMemCopy((void *)&pChild->pwszName[(cchName + 1) * 2],
     1756                                                        &pchPath[offName], cchName);
     1757        ((char *)pChild->pszName)[cchName] = '\0';
     1758        pChild->cwcName     = (KU16)kwStrToUtf16(pChild->pszName, (wchar_t *)pChild->pwszName, (cchName + 1) * 2);
     1759
     1760        pChild->cchName     = cchName;
     1761        pChild->cChildren   = 0;
     1762        pChild->papChildren = NULL;
     1763        pChild->pParent     = pParent;
     1764
     1765        pChild->uCacheGen   = pParent->uCacheGen == KFSWOBJ_CACHE_GEN_IGNORE ? KFSWOBJ_CACHE_GEN_IGNORE : g_uFsCacheGeneration;
     1766        pChild->fAttribs    = dwAttr;
     1767        pChild->uLastError  = dwErr;
     1768
     1769        pChild->hCached     = INVALID_HANDLE_VALUE;
     1770        pChild->cbCached    = 0;
     1771        pChild->pbCached    = NULL;
     1772
     1773        if (kwFsLinkChild(pParent, pChild))
     1774            return pChild;
     1775
     1776        kHlpFree(pChild);
     1777    }
     1778    return NULL;
     1779}
     1780
     1781
     1782/**
     1783 * Look up a child node, ANSI version.
     1784 *
     1785 * @returns Pointer to the child if found, NULL if not.
     1786 * @param   pParent             The parent to search the children of.
     1787 * @param   pchName             The child name to search for (not terminated).
     1788 * @param   cchName             The length of the child name.
     1789 */
     1790static PKWFSOBJ kwFsFindChildA(PKWFSOBJ pParent, const char *pchName, KU32 cchName)
     1791{
     1792    /* Check for '.' first. */
     1793    if (cchName != 1 || *pchName != '.')
     1794    {
     1795        KU32        cLeft = pParent->cChildren;
     1796        PKWFSOBJ   *ppCur = pParent->papChildren;
     1797        while (cLeft-- > 0)
     1798        {
     1799            PKWFSOBJ pCur = *ppCur++;
     1800            if (   pCur->cchName == cchName
     1801                && _memicmp(pCur->pszName, pchName, cchName) == 0)
     1802            {
     1803                if (   pCur->uCacheGen != KFSWOBJ_CACHE_GEN_IGNORE
     1804                    && pCur->uCacheGen != g_uFsCacheGeneration)
     1805                    kwFsRefreshNode(pCur);
     1806                return pCur;
     1807            }
     1808        }
     1809        return NULL;
     1810    }
     1811    return pParent;
     1812}
     1813
     1814
     1815/**
     1816 * Walk the file system tree for the given absolute path, entering it into the
     1817 * hash table.
     1818 *
     1819 * This will create any missing nodes while walking.
     1820 *
     1821 * @returns Pointer to the tree node corresponding to @a pszPath.
     1822 *          NULL if we ran out of memory.
     1823 * @param   pszPath             The path to walk.
     1824 * @param   cchPath             The length of the path.
     1825 * @param   uHashPath           The hash of the path.
     1826 * @param   idxHashTab          Index into the hash table.
     1827 */
     1828static PKWFSOBJ kwFsLookupAbsoluteA(const char *pszPath, KU32 cchPath, KU32 uHashPath, KU32 idxHashTab)
     1829{
     1830    PKWFSOBJ    pParent = &g_FsRoot;
     1831    KU32        off;
     1832    KWFS_LOG(("kwFsLookupAbsoluteA(%s)\n", pszPath));
     1833
     1834    kHlpAssert(IS_ALPHA(pszPath[0]));
     1835    kHlpAssert(pszPath[1] == ':');
     1836    kHlpAssert(IS_SLASH(pszPath[2]));
     1837
     1838    off = 0;
     1839    for (;;)
     1840    {
     1841        PKWFSOBJ    pChild;
     1842
     1843        /* Find the end of the component. */
     1844        char        ch;
     1845        KU32        cchSlashes = 0;
     1846        KU32        offEnd = off + 1;
     1847        while ((ch = pszPath[offEnd]) != '\0')
     1848        {
     1849            if (!IS_SLASH(ch))
     1850                offEnd++;
     1851            else
     1852            {
     1853                do
     1854                    cchSlashes++;
     1855                while (IS_SLASH(pszPath[offEnd + cchSlashes]));
     1856                break;
     1857            }
     1858        }
     1859
     1860        /* Search the current node for the name. */
     1861        pChild = kwFsFindChildA(pParent, &pszPath[off], offEnd - off);
     1862        if (!pChild)
     1863        {
     1864            pChild = kwFsCreateChildA(pParent, pszPath, off, offEnd - off);
     1865            if (!pChild)
     1866                break;
     1867        }
     1868        off = offEnd + cchSlashes;
     1869        if (   cchSlashes == 0
     1870            || off >= cchPath)
     1871        {
     1872            kwFsCreateHashTabEntryA(pChild, pszPath, cchPath, uHashPath, idxHashTab);
     1873            return pChild;
     1874        }
     1875
     1876        /* Check that it's a directory (won't match INVALID_FILE_ATTRIBUTES). */
     1877        if (!(pChild->fAttribs & FILE_ATTRIBUTE_DIRECTORY))
     1878            return &g_FsPathNotFound;
     1879
     1880        pParent = pChild;
     1881    }
     1882
     1883    return NULL;
     1884}
     1885
     1886
     1887/**
     1888 * This deals with paths that are relative and paths that contains '..'
     1889 * elements.
     1890 *
     1891 * @returns Pointer to object corresponding to @a pszPath on success.
     1892 *          NULL if this isn't a path we care to cache.
     1893 * @param   pszPath             The path.
     1894 * @param   cchPath             The length of the path.
     1895 * @param   uHashPath           The hash of the path.
     1896 * @param   idxHashTab          The path table index.
     1897 */
     1898static PKWFSOBJ kwFsLookupSlowA(const char *pszPath, KU32 cchPath, KU32 uHashPath, KU32 idxHashTab)
     1899{
     1900    /* Turns out getcwd/_getdcwd uses GetFullPathName internall, so just call it directly here. */
     1901    char szFull[2048];
     1902    UINT cchFull = GetFullPathNameA(pszPath, sizeof(szFull), szFull, NULL);
     1903    if (   cchFull >= 3
     1904        && cchFull < sizeof(szFull))
     1905    {
     1906        KWFS_LOG(("kwFsLookupSlowA(%s)\n", pszPath));
     1907        if (   szFull[1] == ':'
     1908            && IS_SLASH(szFull[2])
     1909            && IS_ALPHA(szFull[0]) )
     1910        {
     1911            KU32     uHashPath2  = kwStrHash(szFull);
     1912            PKWFSOBJ pFsObj = kwFsLookupAbsoluteA(szFull, cchFull, uHashPath2, uHashPath2 % K_ELEMENTS(g_apFsAnsiPaths));
     1913            if (pFsObj)
     1914            {
     1915                kwFsCreateHashTabEntryA(pFsObj, pszPath, cchPath, uHashPath, idxHashTab);
     1916                return pFsObj;
     1917            }
     1918        }
     1919
     1920        /* It's worth remembering uncacheable paths in the hash table. */
     1921        kwFsCreateHashTabEntryA(NULL /*pFsObj*/, pszPath, cchPath, uHashPath, idxHashTab);
     1922    }
     1923    return NULL;
     1924}
     1925
     1926
     1927/**
     1928 * Looks up a KWFSOBJ for the given ANSI path.
     1929 *
     1930 * This will first try the hash table.  If not in the hash table, the file
     1931 * system cache tree is walked, missing bits filled in and finally a hash table
     1932 * entry is created.
     1933 *
     1934 * Only drive letter paths are cachable.  We don't do any UNC paths at this
     1935 * point.
     1936 *
     1937 *
     1938 * @returns Pointer to object corresponding to @a pszPath on success.
     1939 *          NULL if not a path we care to cache.
     1940 * @param   pszPath             The path to lookup.
     1941 */
     1942static PKWFSOBJ kwFsLookupA(const char *pszPath)
     1943{
     1944    /*
     1945     * Do hash table lookup of the path.
     1946     */
     1947    KU32        uHashPath;
     1948    KU32        cchPath    = (KU32)kwStrHashEx(pszPath, &uHashPath);
     1949    KU32        idxHashTab = uHashPath % K_ELEMENTS(g_apFsAnsiPaths);
     1950    PKWFSHASHA  pHashEntry = g_apFsAnsiPaths[idxHashTab];
     1951    if (pHashEntry)
     1952    {
     1953        do
     1954        {
     1955            if (   pHashEntry->uHashPath == uHashPath
     1956                && pHashEntry->cchPath   == cchPath
     1957                && kHlpMemComp(pHashEntry->pszPath, pszPath, cchPath) == 0)
     1958            {
     1959                KWFS_LOG(("kwFsLookupA(%s) - hit %p\n", pszPath, pHashEntry->pFsObj));
     1960                return pHashEntry->pFsObj;
     1961            }
     1962            pHashEntry = pHashEntry->pNext;
     1963        } while (pHashEntry);
     1964    }
     1965
     1966    /*
     1967     * Create an entry for it by walking the file system cache and filling in the blanks.
     1968     */
     1969    if (   cchPath > 0
     1970        && cchPath < 1024)
     1971    {
     1972        /* Is absolute without any '..' bits? */
     1973        if (   cchPath >= 3
     1974            && pszPath[1] == ':'
     1975            && IS_SLASH(pszPath[2])
     1976            && IS_ALPHA(pszPath[0])
     1977            && !kwFsHasDotDot(pszPath, cchPath) )
     1978            return kwFsLookupAbsoluteA(pszPath, cchPath, uHashPath, idxHashTab);
     1979
     1980        /* Not UNC? */
     1981        if (   cchPath < 2
     1982            || !IS_SLASH(pszPath[0])
     1983            || !IS_SLASH(pszPath[1]) )
     1984            return kwFsLookupSlowA(pszPath, cchPath, uHashPath, idxHashTab);
     1985
     1986
     1987        /* It's worth remembering uncacheable paths in the hash table. */
     1988        kwFsCreateHashTabEntryA(NULL /*pFsObj*/, pszPath, cchPath, uHashPath, idxHashTab);
     1989    }
     1990    return NULL;
     1991}
     1992
    11271993
    11281994
     
    12682134static void __cdecl kwSandbox_msvcrt_exit(int rcExitCode)
    12692135{
    1270     kwDbgPrintf("kwSandbox_msvcrt_exit: %d\n", rcExitCode);
     2136    KW_LOG(("kwSandbox_msvcrt_exit: %d\n", rcExitCode));
    12712137    kwSandbox_Kernel32_ExitProcess(rcExitCode);
    12722138}
     
    12772143{
    12782144    /* Quick. */
    1279     kwDbgPrintf("kwSandbox_msvcrt__exit %d\n", rcExitCode);
     2145    KW_LOG(("kwSandbox_msvcrt__exit %d\n", rcExitCode));
    12802146    kwSandbox_Kernel32_ExitProcess(rcExitCode);
    12812147}
     
    12852151static void __cdecl kwSandbox_msvcrt__cexit(int rcExitCode)
    12862152{
    1287     kwDbgPrintf("kwSandbox_msvcrt__cexit: %d\n", rcExitCode);
     2153    KW_LOG(("kwSandbox_msvcrt__cexit: %d\n", rcExitCode));
    12882154    kwSandbox_Kernel32_ExitProcess(rcExitCode);
    12892155}
     
    12932159static void __cdecl kwSandbox_msvcrt__c_exit(int rcExitCode)
    12942160{
    1295     kwDbgPrintf("kwSandbox_msvcrt__c_exit: %d\n", rcExitCode);
     2161    KW_LOG(("kwSandbox_msvcrt__c_exit: %d\n", rcExitCode));
    12962162    kwSandbox_Kernel32_ExitProcess(rcExitCode);
    12972163}
     
    13012167static void __cdecl kwSandbox_msvcrt__amsg_exit(int iMsgNo)
    13022168{
    1303     kwDbgPrintf("\nRuntime error #%u!\n", iMsgNo);
     2169    KW_LOG(("\nRuntime error #%u!\n", iMsgNo));
    13042170    kwSandbox_Kernel32_ExitProcess(255);
     2171}
     2172
     2173
     2174/** CRT - terminate().  */
     2175static void __cdecl kwSandbox_msvcrt_terminate(void)
     2176{
     2177    KW_LOG(("\nRuntime - terminate!\n"));
     2178    kwSandbox_Kernel32_ExitProcess(254);
    13052179}
    13062180
     
    14852359static DWORD WINAPI kwSandbox_Kernel32_GetEnvironmentVariableW(LPCWSTR pwszVar, LPWSTR pwszValue, DWORD cbValue)
    14862360{
    1487     kwDbgPrintf("GetEnvironmentVariableW: '%ls'\n", pwszVar);
     2361    KW_LOG(("GetEnvironmentVariableW: '%ls'\n", pwszVar));
    14882362    //__debugbreak();
    14892363    //SetLastError(ERROR_ENVVAR_NOT_FOUND);
     
    15042378static BOOL WINAPI kwSandbox_Kernel32_SetEnvironmentVariableW(LPCWSTR pwszVar, LPCWSTR pwszValue)
    15052379{
    1506     kwDbgPrintf("SetEnvironmentVariableW: '%ls' = '%ls'\n", pwszVar, pwszValue);
     2380    KW_LOG(("SetEnvironmentVariableW: '%ls' = '%ls'\n", pwszVar, pwszValue));
    15072381    return SetEnvironmentVariableW(pwszVar, pwszValue);
    15082382    //__debugbreak();
     
    15542428static errno_t __cdecl kwSandbox_msvcrt__wputenv_s(const wchar_t *pwszVar, const wchar_t *pwszValue)
    15552429{
    1556     kwDbgPrintf("_wputenv_s: '%ls' = '%ls'\n", pwszVar, pwszValue);
     2430    KW_LOG(("_wputenv_s: '%ls' = '%ls'\n", pwszVar, pwszValue));
    15572431    //__debugbreak();
    15582432    return SetEnvironmentVariableW(pwszVar, pwszValue) ? 0 : -1;
     
    18632737            static int s_cDbgGets = 0;
    18642738            s_cDbgGets++;
    1865             kwDbgPrintf("GetProcAddress(%s, %s) -> %p [%d]\n", pMod->pszPath, pszProc, (KUPTR)uValue, s_cDbgGets);
     2739            KW_LOG(("GetProcAddress(%s, %s) -> %p [%d]\n", pMod->pszPath, pszProc, (KUPTR)uValue, s_cDbgGets));
    18662740            kwLdrModuleRelease(pMod);
    18672741            //if (s_cGets >= 3)
     
    19132787
    19142788
     2789/*
     2790 *
     2791 * File access APIs (for speeding them up).
     2792 * File access APIs (for speeding them up).
     2793 * File access APIs (for speeding them up).
     2794 *
     2795 */
     2796
     2797/**
     2798 * Checks if the file extension indicates that the file/dir is something we
     2799 * ought to cache.
     2800 *
     2801 * @returns K_TRUE if cachable, K_FALSE if not.
     2802 * @param   pszExt              The kHlpGetExt result.
     2803 * @param   fAttrQuery          Set if it's for an attribute query, clear if for
     2804 *                              file creation.
     2805 */
     2806static KBOOL kwFsIsCachableExtensionA(const char *pszExt, KBOOL fAttrQuery)
     2807{
     2808    char const chFirst = *pszExt;
     2809
     2810    /* C++ header without an extension or a directory. */
     2811    if (chFirst == '\0')
     2812        return K_TRUE;
     2813
     2814    /* C Header: .h */
     2815    if (chFirst == 'h' || chFirst == 'H')
     2816    {
     2817        char        chThird;
     2818        char const  chSecond = pszExt[1];
     2819        if (chSecond == '\0')
     2820            return K_TRUE;
     2821        chThird = pszExt[2];
     2822
     2823        /* C++ Header: .hpp, .hxx */
     2824        if (   (chSecond == 'p' || chSecond == 'P')
     2825            && (chThird  == 'p' || chThird  == 'P')
     2826            && pszExt[3] == '\0')
     2827            return K_TRUE;
     2828        if (   (chSecond == 'x' || chSecond == 'X')
     2829            && (chThird  == 'x' || chThird  == 'X')
     2830            && pszExt[3] == '\0')
     2831            return K_TRUE;
     2832
     2833    }
     2834    /* Misc starting with i. */
     2835    else if (chFirst == 'i' || chFirst == 'I')
     2836    {
     2837        char const chSecond = pszExt[1];
     2838        if (chSecond != '\0')
     2839        {
     2840            if (chSecond == 'n' || chSecond == 'N')
     2841            {
     2842                char const chThird = pszExt[2];
     2843
     2844                /* C++ inline header: .inl */
     2845                if (   (chThird == 'l' || chThird == 'L')
     2846                    && pszExt[3] == '\0')
     2847                    return K_TRUE;
     2848
     2849                /* Assembly include file: .inc */
     2850                if (   (chThird == 'c' || chThird == 'C')
     2851                    && pszExt[3] == '\0')
     2852                    return K_TRUE;
     2853            }
     2854        }
     2855    }
     2856    else if (fAttrQuery)
     2857    {
     2858        /* Dynamic link library: .dll */
     2859        if (chFirst == 'd' || chFirst == 'D')
     2860        {
     2861            char const chSecond = pszExt[1];
     2862            if (chSecond == 'l' || chSecond == 'L')
     2863            {
     2864                char const chThird = pszExt[2];
     2865                if (chThird == 'l' || chThird == 'L')
     2866                    return K_TRUE;
     2867            }
     2868        }
     2869        /* Executable file: .exe */
     2870        else if (chFirst == 'e' || chFirst == 'E')
     2871        {
     2872            char const chSecond = pszExt[1];
     2873            if (chSecond == 'x' || chSecond == 'X')
     2874            {
     2875                char const chThird = pszExt[2];
     2876                if (chThird == 'e' || chThird == 'e')
     2877                    return K_TRUE;
     2878            }
     2879        }
     2880    }
     2881
     2882    return K_FALSE;
     2883}
     2884
     2885
     2886/**
     2887 * Checks if the extension of the given UTF-16 path indicates that the file/dir
     2888 * should be cached.
     2889 *
     2890 * @returns K_TRUE if cachable, K_FALSE if not.
     2891 * @param   pwszPath            The UTF-16 path to examine.
     2892 * @param   fAttrQuery          Set if it's for an attribute query, clear if for
     2893 *                              file creation.
     2894 */
     2895static KBOOL kwFsIsCachablePathExtensionW(const wchar_t *pwszPath, KBOOL fAttrQuery)
     2896{
     2897    /*
     2898     * Extract the extension, check that it's in the applicable range, roughly
     2899     * convert it to ASCII/ANSI, and feed it to kwFsIsCachableExtensionA for
     2900     * the actual check.  This avoids a lot of code duplication.
     2901     */
     2902    wchar_t         wc;
     2903    char            szExt[4];
     2904    KSIZE           cwcExt;
     2905    wchar_t const  *pwszExt = kwFsPathGetExtW(pwszPath, &cwcExt);
     2906    switch (cwcExt)
     2907    {
     2908        case 3: if ((wchar_t)(szExt[2] = (char)(wc = pwszExt[2])) == wc) { /*likely*/ } else break;
     2909        case 2: if ((wchar_t)(szExt[1] = (char)(wc = pwszExt[1])) == wc) { /*likely*/ } else break;
     2910        case 1: if ((wchar_t)(szExt[0] = (char)(wc = pwszExt[0])) == wc) { /*likely*/ } else break;
     2911        case 0:
     2912            szExt[cwcExt] = '\0';
     2913            return kwFsIsCachableExtensionA(szExt, fAttrQuery);
     2914    }
     2915    return K_FALSE;
     2916}
     2917
     2918
     2919/** Kernel32 - CreateFileA */
     2920static HANDLE WINAPI kwSandbox_Kernel32_CreateFileA(LPCSTR pszFilename, DWORD dwDesiredAccess, DWORD dwShareMode,
     2921                                                    LPSECURITY_ATTRIBUTES pSecAttrs, DWORD dwCreationDisposition,
     2922                                                    DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
     2923{
     2924    HANDLE hFile;
     2925    if (dwCreationDisposition == FILE_OPEN)
     2926    {
     2927        if (   dwDesiredAccess == GENERIC_READ
     2928            || dwDesiredAccess == FILE_GENERIC_READ)
     2929        {
     2930            if (dwShareMode & FILE_SHARE_READ)
     2931            {
     2932                if (   !pSecAttrs
     2933                    || (   pSecAttrs->bInheritHandle == FALSE
     2934                        && pSecAttrs->nLength == 0) ) /** @todo This one might not make a lot of sense... */
     2935                {
     2936                    const char *pszExt = kHlpGetExt(pszFilename);
     2937                    if (kwFsIsCachableExtensionA(pszExt, K_FALSE /*fAttrQuery*/))
     2938                    {
     2939                        /** @todo later.   */
     2940                        hFile = CreateFileA(pszFilename, dwDesiredAccess, dwShareMode, pSecAttrs,
     2941                                            dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
     2942                        KWFS_LOG(("CreateFileA(%s) - cachable -> %p\n", pszFilename, hFile));
     2943                        return hFile;
     2944                    }
     2945                }
     2946            }
     2947        }
     2948    }
     2949
     2950    hFile = CreateFileA(pszFilename, dwDesiredAccess, dwShareMode, pSecAttrs,
     2951                        dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
     2952    KWFS_LOG(("CreateFileA(%s) -> %p\n", pszFilename, hFile));
     2953    return hFile;
     2954}
     2955
     2956
     2957/** Kernel32 - CreateFileW */
     2958static HANDLE WINAPI kwSandbox_Kernel32_CreateFileW(LPCWSTR pwszFilename, DWORD dwDesiredAccess, DWORD dwShareMode,
     2959                                                    LPSECURITY_ATTRIBUTES pSecAttrs, DWORD dwCreationDisposition,
     2960                                                    DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
     2961{
     2962    HANDLE hFile;
     2963    if (dwCreationDisposition == FILE_OPEN)
     2964    {
     2965        if (   dwDesiredAccess == GENERIC_READ
     2966            || dwDesiredAccess == FILE_GENERIC_READ)
     2967        {
     2968            if (dwShareMode & FILE_SHARE_READ)
     2969            {
     2970                if (   !pSecAttrs
     2971                    || (   pSecAttrs->bInheritHandle == FALSE
     2972                        && pSecAttrs->nLength == 0) ) /** @todo This one might not make a lot of sense... */
     2973                {
     2974                    if (kwFsIsCachablePathExtensionW(pwszFilename, K_FALSE /*fAttrQuery*/))
     2975                    {
     2976                        /** @todo later.   */
     2977
     2978                        hFile = CreateFileW(pwszFilename, dwDesiredAccess, dwShareMode, pSecAttrs,
     2979                                            dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
     2980
     2981                        KWFS_LOG(("CreateFileW(%ls) - cachable -> %p\n", pwszFilename, hFile));
     2982                        return hFile;
     2983                    }
     2984                }
     2985            }
     2986        }
     2987    }
     2988    hFile = CreateFileW(pwszFilename, dwDesiredAccess, dwShareMode, pSecAttrs,
     2989                        dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
     2990    KWFS_LOG(("CreateFileW(%ls) -> %p\n", pwszFilename, hFile));
     2991    return hFile;
     2992}
     2993
     2994
     2995/** Kernel32 - SetFilePointer */
     2996static DWORD WINAPI kwSandbox_Kernel32_SetFilePointer(HANDLE hFile, LONG cbMove, PLONG pcbMoveHi, DWORD dwMoveMethod)
     2997{
     2998    KWFS_LOG(("SetFilePointer(%p)\n", hFile));
     2999    return SetFilePointer(hFile, cbMove, pcbMoveHi, dwMoveMethod);
     3000}
     3001
     3002
     3003/** Kernel32 - SetFilePointerEx */
     3004static BOOL WINAPI kwSandbox_Kernel32_SetFilePointerEx(HANDLE hFile, LARGE_INTEGER pcbMove, PLARGE_INTEGER poffNew,
     3005                                                       DWORD dwMoveMethod)
     3006{
     3007    KWFS_LOG(("SetFilePointerEx(%p)\n", hFile));
     3008    return SetFilePointerEx(hFile, pcbMove, poffNew, dwMoveMethod);
     3009}
     3010
     3011
     3012/** Kernel32 - ReadFile */
     3013static BOOL WINAPI kwSandbox_Kernel32_ReadFile(HANDLE hFile, LPVOID pvBuffer, DWORD cbToWrite, LPDWORD pcbActuallyWritten,
     3014                                               LPOVERLAPPED pOverlapped)
     3015{
     3016    KWFS_LOG(("ReadFile(%p)\n", hFile));
     3017    return ReadFile(hFile, pvBuffer, cbToWrite, pcbActuallyWritten, pOverlapped);
     3018}
     3019
     3020
     3021/** Kernel32 - CloseHandle */
     3022static BOOL WINAPI kwSandbox_Kernel32_CloseHandle(HANDLE hObject)
     3023{
     3024    KWFS_LOG(("CloseHandle(%p)\n", hObject));
     3025    return CloseHandle(hObject);
     3026}
     3027
     3028
     3029/** Kernel32 - GetFileAttributesA. */
     3030static DWORD WINAPI kwSandbox_Kernel32_GetFileAttributesA(LPCSTR pszFilename)
     3031{
     3032    DWORD       fRet;
     3033    const char *pszExt = kHlpGetExt(pszFilename);
     3034    if (kwFsIsCachableExtensionA(pszExt, K_TRUE /*fAttrQuery*/))
     3035    {
     3036        PKWFSOBJ pFsObj = kwFsLookupA(pszFilename);
     3037        if (pFsObj)
     3038        {
     3039            if (pFsObj->fAttribs == INVALID_FILE_ATTRIBUTES)
     3040                SetLastError(pFsObj->uLastError);
     3041            KWFS_LOG(("GetFileAttributesA(%s) -> %#x [cached]\n", pszFilename, pFsObj->fAttribs));
     3042            return pFsObj->fAttribs;
     3043        }
     3044    }
     3045
     3046    fRet = GetFileAttributesA(pszFilename);
     3047    KWFS_LOG(("GetFileAttributesA(%s) -> %#x\n", pszFilename, fRet));
     3048    return fRet;
     3049}
     3050
     3051
     3052/** Kernel32 - GetFileAttributesW. */
     3053static DWORD WINAPI kwSandbox_Kernel32_GetFileAttributesW(LPCWSTR pwszFilename)
     3054{
     3055    DWORD fRet;
     3056    if (kwFsIsCachablePathExtensionW(pwszFilename, K_TRUE /*fAttrQuery*/))
     3057    {
     3058        /** @todo rewrite to pure UTF-16. */
     3059        char szTmp[2048];
     3060        KSIZE cch = kwUtf16ToStr(pwszFilename, szTmp, sizeof(szTmp));
     3061        if (cch < sizeof(szTmp))
     3062            return kwSandbox_Kernel32_GetFileAttributesA(szTmp);
     3063    }
     3064
     3065    fRet = GetFileAttributesW(pwszFilename);
     3066    KWFS_LOG(("GetFileAttributesW(%ls) -> %#x\n", pwszFilename, fRet));
     3067    return fRet;
     3068}
     3069
     3070
     3071/** Kernel32 - GetShortPathNameW - cl1[xx].dll of VS2010 does this to the
     3072 * directory containing each include file.  We cache the result to speed
     3073 * things up a little. */
     3074static DWORD WINAPI kwSandbox_Kernel32_GetShortPathNameW(LPCWSTR pwszLongPath, LPWSTR pwszShortPath, DWORD cwcShortPath)
     3075{
     3076    DWORD cwcRet;
     3077    if (kwFsIsCachablePathExtensionW(pwszLongPath, K_TRUE /*fAttrQuery*/))
     3078    {
     3079        /** @todo proper implementation later, for now just copy it over as it. */
     3080        KSIZE cwcLongPath = kwUtf16Len(pwszLongPath);
     3081        cwcRet = kwUtf16CopyStyle1(pwszLongPath, pwszShortPath, cwcShortPath);
     3082        KWFS_LOG(("GetShortPathNameW(%ls) -> '%*.*ls' & %#x [cached]\n",
     3083                  pwszLongPath, K_MIN(cwcShortPath, cwcRet), K_MIN(cwcShortPath, cwcRet), pwszShortPath, cwcRet));
     3084    }
     3085    else
     3086    {
     3087        cwcRet = GetShortPathNameW(pwszLongPath, pwszShortPath, cwcShortPath);
     3088        KWFS_LOG(("GetShortPathNameW(%ls) -> '%*.*ls' & %#x\n",
     3089                  pwszLongPath, K_MIN(cwcShortPath, cwcRet), K_MIN(cwcShortPath, cwcRet), pwszShortPath, cwcRet));
     3090    }
     3091    return cwcRet;
     3092}
     3093
     3094
     3095
    19153096/**
    19163097 * Functions that needs replacing for sandboxed execution.
     
    19183099KWREPLACEMENTFUNCTION const g_aSandboxReplacements[] =
    19193100{
    1920 #define TUPLE(a_sz) a_sz, sizeof(a_sz) - 1
    19213101    /*
    19223102     * Kernel32.dll and friends.
     
    19503130    { TUPLE("ExpandEnvironmentStringsW"),   NULL,       (KUPTR)kwSandbox_Kernel32_ExpandEnvironmentStringsW },
    19513131
     3132    { TUPLE("CreateFileA"),                 NULL,       (KUPTR)kwSandbox_Kernel32_CreateFileA },
     3133    { TUPLE("CreateFileW"),                 NULL,       (KUPTR)kwSandbox_Kernel32_CreateFileW },
     3134    { TUPLE("ReadFile"),                    NULL,       (KUPTR)kwSandbox_Kernel32_ReadFile },
     3135    { TUPLE("SetFilePointer"),              NULL,       (KUPTR)kwSandbox_Kernel32_SetFilePointer },
     3136    { TUPLE("SetFilePointerEx"),            NULL,       (KUPTR)kwSandbox_Kernel32_SetFilePointerEx },
     3137    { TUPLE("CloseHandle"),                 NULL,       (KUPTR)kwSandbox_Kernel32_CloseHandle },
     3138    { TUPLE("GetFileAttributesA"),          NULL,       (KUPTR)kwSandbox_Kernel32_GetFileAttributesA },
     3139    { TUPLE("GetFileAttributesW"),          NULL,       (KUPTR)kwSandbox_Kernel32_GetFileAttributesW },
     3140    { TUPLE("GetShortPathNameW"),           NULL,       (KUPTR)kwSandbox_Kernel32_GetShortPathNameW },
     3141
    19523142    /*
    19533143     * MS Visual C++ CRTs.
     
    19583148    { TUPLE("_c_exit"),                     NULL,       (KUPTR)kwSandbox_msvcrt__c_exit },
    19593149    { TUPLE("_amsg_exit"),                  NULL,       (KUPTR)kwSandbox_msvcrt__amsg_exit },
     3150    { TUPLE("terminate"),                   NULL,       (KUPTR)kwSandbox_msvcrt_terminate },
    19603151
    19613152    { TUPLE("_beginthread"),                NULL,       (KUPTR)kwSandbox_msvcrt__beginthread },
     
    19973188    { TUPLE("__p__environ"),                NULL,       (KUPTR)kwSandbox_msvcrt___p__environ },
    19983189    { TUPLE("__p__wenviron"),               NULL,       (KUPTR)kwSandbox_msvcrt___p__wenviron },
    1999     /// @todo terminate
    20003190};
    20013191/** Number of entries in g_aReplacements. */
    20023192KU32 const                  g_cSandboxReplacements = K_ELEMENTS(g_aSandboxReplacements);
     3193
     3194
     3195/**
     3196 * Functions that needs replacing in natively loaded DLLs when doing sandboxed
     3197 * execution.
     3198 */
     3199KWREPLACEMENTFUNCTION const g_aSandboxNativeReplacements[] =
     3200{
     3201    /*
     3202     * Kernel32.dll and friends.
     3203     */
     3204    { TUPLE("ExitProcess"),                 NULL,       (KUPTR)kwSandbox_Kernel32_ExitProcess },
     3205    { TUPLE("TerminateProcess"),            NULL,       (KUPTR)kwSandbox_Kernel32_TerminateProcess },
     3206
     3207#if 0
     3208    { TUPLE("CreateThread"),                NULL,       (KUPTR)kwSandbox_Kernel32_CreateThread },
     3209#endif
     3210
     3211#if 0
     3212    { TUPLE("CreateFileA"),                 NULL,       (KUPTR)kwSandbox_Kernel32_CreateFileA },
     3213    { TUPLE("CreateFileW"),                 NULL,       (KUPTR)kwSandbox_Kernel32_CreateFileW },
     3214    { TUPLE("ReadFile"),                    NULL,       (KUPTR)kwSandbox_Kernel32_ReadFile },
     3215    { TUPLE("SetFilePointer"),              NULL,       (KUPTR)kwSandbox_Kernel32_SetFilePointer },
     3216    { TUPLE("SetFilePointerEx"),            NULL,       (KUPTR)kwSandbox_Kernel32_SetFilePointerEx },
     3217    { TUPLE("CloseHandle"),                 NULL,       (KUPTR)kwSandbox_Kernel32_CloseHandle },
     3218#endif
     3219    { TUPLE("GetFileAttributesA"),          NULL,       (KUPTR)kwSandbox_Kernel32_GetFileAttributesA },
     3220    { TUPLE("GetFileAttributesW"),          NULL,       (KUPTR)kwSandbox_Kernel32_GetFileAttributesW },
     3221    { TUPLE("GetShortPathNameW"),           NULL,       (KUPTR)kwSandbox_Kernel32_GetShortPathNameW },
     3222
     3223    /*
     3224     * MS Visual C++ CRTs.
     3225     */
     3226    { TUPLE("exit"),                        NULL,       (KUPTR)kwSandbox_msvcrt_exit },
     3227    { TUPLE("_exit"),                       NULL,       (KUPTR)kwSandbox_msvcrt__exit },
     3228    { TUPLE("_cexit"),                      NULL,       (KUPTR)kwSandbox_msvcrt__cexit },
     3229    { TUPLE("_c_exit"),                     NULL,       (KUPTR)kwSandbox_msvcrt__c_exit },
     3230    { TUPLE("_amsg_exit"),                  NULL,       (KUPTR)kwSandbox_msvcrt__amsg_exit },
     3231    { TUPLE("terminate"),                   NULL,       (KUPTR)kwSandbox_msvcrt_terminate },
     3232
     3233#if 0 /* used by mspdbXXX.dll */
     3234    { TUPLE("_beginthread"),                NULL,       (KUPTR)kwSandbox_msvcrt__beginthread },
     3235    { TUPLE("_beginthreadex"),              NULL,       (KUPTR)kwSandbox_msvcrt__beginthreadex },
     3236#endif
     3237};
     3238/** Number of entries in g_aSandboxNativeReplacements. */
     3239KU32 const                  g_cSandboxNativeReplacements = K_ELEMENTS(g_aSandboxNativeReplacements);
    20033240
    20043241
     
    20963333    pPeb->ProcessParameters->CommandLine.Length = (USHORT)cwc * sizeof(wchar_t);
    20973334
     3335
     3336    g_uFsCacheGeneration++;
     3337    if (g_uFsCacheGeneration == KFSWOBJ_CACHE_GEN_IGNORE)
     3338        g_uFsCacheGeneration++;
    20983339    return 0;
    20993340}
     
    21133354
    21143355    *prcExitCode            = 256;
    2115 kwDbgPrintf("GetCommandLineA: '%s'\n", GetCommandLineA());
    21163356
    21173357    /*
     
    21213361    if (rc == 0)
    21223362    {
    2123 
    21243363        /*
    21253364         * Do module initialization.
     
    21833422        {
    21843423            case KWTOOLTYPE_SANDBOXED:
    2185                 kwDbgPrintf("Sandboxing tool %s\n", pTool->pszPath);
     3424                KW_LOG(("Sandboxing tool %s\n", pTool->pszPath));
    21863425                rc = kwSandboxExec(pTool, pszCmdLine, &rcExitCode);
    21873426                break;
    21883427
    21893428            case KWTOOLTYPE_WATCOM:
    2190                 kwDbgPrintf("TODO: Watcom style tool %s\n", pTool->pszPath);
     3429                KW_LOG(("TODO: Watcom style tool %s\n", pTool->pszPath));
    21913430                rc = rcExitCode = 2;
    21923431                break;
    21933432
    21943433            case KWTOOLTYPE_EXEC:
    2195                 kwDbgPrintf("TODO: Direct exec tool %s\n", pTool->pszPath);
     3434                KW_LOG(("TODO: Direct exec tool %s\n", pTool->pszPath));
    21963435                rc = rcExitCode = 2;
    21973436                break;
     
    22023441                break;
    22033442        }
    2204         kwDbgPrintf("rcExitCode=%d (rc=%d)\n", rcExitCode, rc);
     3443        KW_LOG(("rcExitCode=%d (rc=%d)\n", rcExitCode, rc));
    22053444    }
    22063445    else
     
    22123451int main(int argc, char **argv)
    22133452{
     3453    int rc = 0;
    22143454    int i;
    2215     int rc;
    22163455    argv[2] = "\"E:/vbox/svn/trunk/tools/win.x86/vcc/v10sp1/bin/amd64/cl.exe\" -c -c -TP -nologo -Zi -Zi -Zl -GR- -EHsc -GF -Zc:wchar_t- -Oy- -MT -W4 -Wall -wd4065 -wd4996 -wd4127 -wd4706 -wd4201 -wd4214 -wd4510 -wd4512 -wd4610 -wd4514 -wd4820 -wd4365 -wd4987 -wd4710 -wd4061 -wd4986 -wd4191 -wd4574 -wd4917 -wd4711 -wd4611 -wd4571 -wd4324 -wd4505 -wd4263 -wd4264 -wd4738 -wd4242 -wd4244 -WX -RTCsu -IE:/vbox/svn/trunk/tools/win.x86/vcc/v10sp1/include -IE:/vbox/svn/trunk/tools/win.x86/vcc/v10sp1/atlmfc/include -IE:/vbox/svn/trunk/tools/win.x86/sdk/v7.1/Include -IE:/vbox/svn/trunk/include -IE:/vbox/svn/trunk/out/win.amd64/debug -IE:/vbox/svn/trunk/tools/win.x86/vcc/v10sp1/include -IE:/vbox/svn/trunk/tools/win.x86/vcc/v10sp1/atlmfc/include -DVBOX -DVBOX_WITH_64_BITS_GUESTS -DVBOX_WITH_REM -DVBOX_WITH_RAW_MODE -DDEBUG -DDEBUG_bird -DDEBUG_USERNAME=bird -DRT_OS_WINDOWS -D__WIN__ -DRT_ARCH_AMD64 -D__AMD64__ -D__WIN64__ -DVBOX_WITH_DEBUGGER -DRT_LOCK_STRICT -DRT_LOCK_STRICT_ORDER -DIN_RING3 -DLOG_DISABLED -DIN_BLD_PROG -D_CRT_SECURE_NO_DEPRECATE -FdE:/vbox/svn/trunk/out/win.amd64/debug/obj/VBoxBs2Linker/VBoxBs2Linker-obj.pdb -FD -FoE:/vbox/svn/trunk/out/win.amd64/debug/obj/VBoxBs2Linker/VBoxBs2Linker.obj E:\\vbox\\svn\\trunk\\src\\VBox\\ValidationKit\\bootsectors\\VBoxBs2Linker.cpp";
    2217     //rc = kwExecCmdLine(argv[1], argv[2]);
    2218     //rc = kwExecCmdLine(argv[1], argv[2]);
     3456#if 0
     3457    rc = kwExecCmdLine(argv[1], argv[2]);
     3458    rc = kwExecCmdLine(argv[1], argv[2]);
     3459    K_NOREF(i);
     3460#else
    22193461// run 2: 34/1024 = 0x0 (0.033203125)
    22203462// run 1: 37/1024 = 0x0 (0.0361328125)
     
    22243466    for (i = 0; i < 1024 && rc == 0; i++)
    22253467        rc = kwExecCmdLine(argv[1], argv[2]);
     3468#endif
    22263469    return rc;
    22273470}
Note: See TracChangeset for help on using the changeset viewer.