Ignore:
Timestamp:
Sep 9, 2016, 4:42:06 PM (9 years ago)
Author:
bird
Message:

output optimizations

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kWorker/kWorker.c

    r2898 r2900  
    6969 * they are included. */
    7070#define WITH_HASH_MD5_CACHE
     71
     72/** @def WITH_CONSOLE_OUTPUT_BUFFERING
     73 * Enables buffering of all console output as well as removal of annoying
     74 * source file echo by cl.exe. */
     75#define WITH_CONSOLE_OUTPUT_BUFFERING
    7176
    7277
     
    276281typedef KFSWCACHEDFILE *PKFSWCACHEDFILE;
    277282
    278 
    279283#ifdef WITH_HASH_MD5_CACHE
     284
    280285/** Pointer to a MD5 hash instance. */
    281286typedef struct KWHASHMD5 *PKWHASHMD5;
     
    307312/** Magic value for KWHASHMD5::uMagic (Les McCann). */
    308313# define KWHASHMD5_MAGIC    KUPTR_C(0x19350923)
     314
    309315#endif /* WITH_HASH_MD5_CACHE */
    310 
    311 
     316#ifdef WITH_TEMP_MEMORY_FILES
    312317
    313318typedef struct KWFSTEMPFILESEG *PKWFSTEMPFILESEG;
     
    345350} KWFSTEMPFILE;
    346351
     352#endif /* WITH_TEMP_MEMORY_FILES */
     353#ifdef WITH_CONSOLE_OUTPUT_BUFFERING
     354
     355/**
     356 * Console line buffer.
     357 */
     358typedef struct KWCONSOLEOUTPUTLINE
     359{
     360    /** The main output handle. */
     361    HANDLE              hOutput;
     362    /** Our backup handle. */
     363    HANDLE              hBackup;
     364    /** Set if this is a console handle. */
     365    KBOOL               fIsConsole;
     366    /** Amount of pending console output in wchar_t's. */
     367    KU32                cwcBuf;
     368    /** The allocated buffer size.   */
     369    KU32                cwcBufAlloc;
     370    /** Pending console output. */
     371    wchar_t            *pwcBuf;
     372} KWCONSOLEOUTPUTLINE;
     373/** Pointer to a console line buffer. */
     374typedef KWCONSOLEOUTPUTLINE *PKWCONSOLEOUTPUTLINE;
     375
     376/**
     377 * Combined console buffer of complete lines.
     378 */
     379typedef struct KWCONSOLEOUTPUT
     380{
     381    /** The console output handle.
     382     * INVALID_HANDLE_VALUE if we haven't got a console and shouldn't be doing any
     383     * combined output buffering. */
     384    HANDLE              hOutput;
     385    /** The current code page for the console. */
     386    KU32                uCodepage;
     387    /** Amount of pending console output in wchar_t's. */
     388    KU32                cwcBuf;
     389    /** Number of times we've flushed it in any way (for cl.exe hack). */
     390    KU32                cFlushes;
     391    /** Pending console output. */
     392    wchar_t             wszBuf[8192];
     393} KWCONSOLEOUTPUT;
     394/** Pointer to a combined console buffer. */
     395typedef KWCONSOLEOUTPUT *PKWCONSOLEOUTPUT;
     396
     397#endif /* WITH_CONSOLE_OUTPUT_BUFFERING */
    347398
    348399/** Handle type.   */
     
    554605    } LastHashRead;
    555606#endif
     607
     608#ifdef WITH_CONSOLE_OUTPUT_BUFFERING
     609    /** Standard output (and whatever else) line buffer. */
     610    KWCONSOLEOUTPUTLINE StdOut;
     611    /** Standard error line buffer. */
     612    KWCONSOLEOUTPUTLINE StdErr;
     613    /** Combined buffer of completed lines. */
     614    KWCONSOLEOUTPUT     Combined;
     615#endif
    556616} KWSANDBOX;
    557617
     
    640700static int kwLdrModuleResolveAndLookup(const char *pszName, PKWMODULE pExe, PKWMODULE pImporter, PKWMODULE *ppMod);
    641701static KBOOL kwSandboxHandleTableEnter(PKWSANDBOX pSandbox, PKWHANDLE pHandle);
     702#ifdef WITH_CONSOLE_OUTPUT_BUFFERING
     703static void kwSandboxConsoleWriteA(PKWSANDBOX pSandbox, PKWCONSOLEOUTPUTLINE pLineBuf, const char *pchBuffer, KU32 cchToWrite);
     704#endif
    642705
    643706
     
    50135076    }
    50145077
     5078#ifdef WITH_CONSOLE_OUTPUT_BUFFERING
     5079    /*
     5080     * Check for stdout and stderr.
     5081     */
     5082    if (   g_Sandbox.StdErr.hOutput == hFile
     5083        || g_Sandbox.StdOut.hOutput == hFile)
     5084    {
     5085        PKWCONSOLEOUTPUTLINE pLineBuf = g_Sandbox.StdErr.hOutput == hFile ? &g_Sandbox.StdErr : &g_Sandbox.StdOut;
     5086        if (pLineBuf->fIsConsole)
     5087        {
     5088            kwSandboxConsoleWriteA(&g_Sandbox, pLineBuf, (const char *)pvBuffer, cbToWrite);
     5089            KWFS_LOG(("WriteFile(console) -> TRUE\n", hFile));
     5090            return TRUE;
     5091        }
     5092    }
     5093#endif
     5094
    50155095    KWFS_LOG(("WriteFile(%p)\n", hFile));
    50165096    return WriteFile(hFile, pvBuffer, cbToWrite, pcbActuallyWritten, pOverlapped);
     
    54995579}
    55005580#endif /* WITH_TEMP_MEMORY_FILES */
     5581
     5582
     5583
     5584#ifdef WITH_CONSOLE_OUTPUT_BUFFERING
     5585
     5586/*
     5587 *
     5588 * Console output buffering.
     5589 * Console output buffering.
     5590 * Console output buffering.
     5591 *
     5592 */
     5593
     5594
     5595/**
     5596 * Write a wide char string to the console.
     5597 *
     5598 * @param   pSandbox            The sandbox which output buffer to flush.
     5599 */
     5600static void kwSandboxConsoleWriteIt(PKWSANDBOX pSandbox, wchar_t const *pwcBuf, KU32 cwcToWrite)
     5601{
     5602    if (cwcToWrite > 0)
     5603    {
     5604        DWORD cwcWritten = 0;
     5605        if (WriteConsoleW(pSandbox->Combined.hOutput, pwcBuf, cwcToWrite, &cwcWritten, NULL))
     5606        {
     5607            if (cwcWritten == cwcToWrite)
     5608            { /* likely */ }
     5609            else
     5610            {
     5611                DWORD off = 0;
     5612                do
     5613                {
     5614                    off += cwcWritten;
     5615                    cwcWritten = 0;
     5616                }
     5617                while (   off < cwcToWrite
     5618                       && WriteConsoleW(pSandbox->Combined.hOutput, &pwcBuf[off], cwcToWrite - off, &cwcWritten, NULL));
     5619                kHlpAssert(off == cwcWritten);
     5620            }
     5621        }
     5622        else
     5623            kHlpAssertFailed();
     5624        pSandbox->Combined.cFlushes++;
     5625    }
     5626}
     5627
     5628
     5629/**
     5630 * Flushes the combined console output buffer.
     5631 *
     5632 * @param   pSandbox            The sandbox which output buffer to flush.
     5633 */
     5634static void kwSandboxConsoleFlushCombined(PKWSANDBOX pSandbox)
     5635{
     5636    if (pSandbox->Combined.cwcBuf > 0)
     5637    {
     5638        kwSandboxConsoleWriteIt(pSandbox, pSandbox->Combined.wszBuf, pSandbox->Combined.cwcBuf);
     5639        pSandbox->Combined.cwcBuf = 0;
     5640    }
     5641}
     5642
     5643
     5644/**
     5645 * For handling combined buffer overflow cases line by line.
     5646 *
     5647 * @param   pSandbox            The sandbox.
     5648 * @param   pwcBuf              What to add to the combined buffer.  Usually a
     5649 *                              line, unless we're really low on buffer space.
     5650 * @param   cwcBuf              The length of what to add.
     5651 * @param   fBrokenLine         Whether this is a broken line.
     5652 */
     5653static void kwSandboxConsoleAddToCombined(PKWSANDBOX pSandbox, wchar_t const *pwcBuf, KU32 cwcBuf, KBOOL fBrokenLine)
     5654{
     5655    if (fBrokenLine)
     5656        kwSandboxConsoleFlushCombined(pSandbox);
     5657    if (pSandbox->Combined.cwcBuf + cwcBuf > K_ELEMENTS(pSandbox->Combined.wszBuf))
     5658    {
     5659        kwSandboxConsoleFlushCombined(pSandbox);
     5660        kwSandboxConsoleWriteIt(pSandbox, pwcBuf, cwcBuf);
     5661    }
     5662    else
     5663    {
     5664        memcpy(&pSandbox->Combined.wszBuf[pSandbox->Combined.cwcBuf], pwcBuf, cwcBuf * sizeof(wchar_t));
     5665        pSandbox->Combined.cwcBuf += cwcBuf;
     5666    }
     5667}
     5668
     5669
     5670/**
     5671 * Called to final flush a line buffer via the combined buffer (if applicable).
     5672 *
     5673 * @param   pSandbox            The sandbox.
     5674 * @param   pLineBuf            The line buffer.
     5675 */
     5676static void kwSandboxConsoleFinalFlushLineBuf(PKWSANDBOX pSandbox, PKWCONSOLEOUTPUTLINE pLineBuf)
     5677{
     5678    if (pLineBuf->cwcBuf > 0)
     5679    {
     5680        if (pLineBuf->fIsConsole)
     5681        {
     5682            if (pLineBuf->cwcBuf < pLineBuf->cwcBufAlloc)
     5683            {
     5684                pLineBuf->pwcBuf[pLineBuf->cwcBuf++] = '\n';
     5685                kwSandboxConsoleAddToCombined(pSandbox, pLineBuf->pwcBuf, pLineBuf->cwcBuf, K_FALSE /*fBrokenLine*/);
     5686            }
     5687            else
     5688            {
     5689                kwSandboxConsoleAddToCombined(pSandbox, pLineBuf->pwcBuf, pLineBuf->cwcBuf, K_TRUE /*fBrokenLine*/);
     5690                kwSandboxConsoleAddToCombined(pSandbox, L"\n", 1, K_TRUE /*fBrokenLine*/);
     5691            }
     5692            pLineBuf->cwcBuf = 0;
     5693        }
     5694        else
     5695        {
     5696            kHlpAssertFailed();
     5697        }
     5698    }
     5699}
     5700
     5701
     5702/**
     5703 * Called at the end of sandboxed execution to flush both stream buffers.
     5704 *
     5705 * @param   pSandbox            The sandbox.
     5706 */
     5707static void kwSandboxConsoleFlushAll(PKWSANDBOX pSandbox)
     5708{
     5709    /*
     5710     * First do the cl.exe source file supression trick, if applicable.
     5711     */
     5712    if (   pSandbox->Combined.cwcBuf >= 3
     5713        && pSandbox->StdOut.cwcBuf == 0
     5714        && pSandbox->StdErr.cwcBuf == 0
     5715        && pSandbox->Combined.cFlushes == 0
     5716        && pSandbox->pTool->u.Sandboxed.enmHint == KWTOOLHINT_VISUAL_CPP_CL)
     5717    {
     5718        KI32    off = pSandbox->Combined.cwcBuf - 1;
     5719        if (pSandbox->Combined.wszBuf[off] == '\n')
     5720        {
     5721            KBOOL fOk = K_TRUE;
     5722            while (off-- > 0)
     5723            {
     5724                wchar_t const wc = pSandbox->Combined.wszBuf[off];
     5725                if (iswalnum(wc) || wc == '.' || wc == ' ' || wc == '_' || wc == '-')
     5726                { /* likely */ }
     5727                else
     5728                {
     5729                    fOk = K_FALSE;
     5730                    break;
     5731                }
     5732            }
     5733            if (fOk)
     5734            {
     5735                pSandbox->Combined.cwcBuf = 0;
     5736                return;
     5737            }
     5738        }
     5739    }
     5740
     5741    /*
     5742     * Flush the two line buffer, the the combined buffer.
     5743     */
     5744    kwSandboxConsoleFinalFlushLineBuf(pSandbox, &pSandbox->StdErr);
     5745    kwSandboxConsoleFinalFlushLineBuf(pSandbox, &pSandbox->StdOut);
     5746    kwSandboxConsoleFlushCombined(pSandbox);
     5747}
     5748
     5749
     5750/**
     5751 * Writes a string to the given output stream.
     5752 *
     5753 * @param   pSandbox            The sandbox.
     5754 * @param   pLineBuf            The line buffer for the output stream.
     5755 * @param   pwcBuffer           The buffer to write.
     5756 * @param   cwcToWrite          The number of wchar_t's in the buffer.
     5757 */
     5758static void kwSandboxConsoleWriteW(PKWSANDBOX pSandbox, PKWCONSOLEOUTPUTLINE pLineBuf, wchar_t const *pwcBuffer, KU32 cwcToWrite)
     5759{
     5760    if (cwcToWrite > 0)
     5761    {
     5762        /*
     5763         * First, find the start of the last incomplete line so we can figure
     5764         * out how much line buffering we need to do.
     5765         */
     5766        KU32 cchLastIncompleteLine;
     5767        KU32 offLastIncompleteLine = cwcToWrite;
     5768        while (   offLastIncompleteLine > 0
     5769               && pwcBuffer[offLastIncompleteLine - 1] != '\n')
     5770            offLastIncompleteLine--;
     5771        cchLastIncompleteLine = cwcToWrite - offLastIncompleteLine;
     5772
     5773        /* Was there anything to line buffer? */
     5774        if (offLastIncompleteLine < cwcToWrite)
     5775        {
     5776            /* Need to grow the line buffer? */
     5777            KU32 cwcNeeded = offLastIncompleteLine != 0 ? offLastIncompleteLine : cchLastIncompleteLine + pLineBuf->cwcBuf;
     5778            if (cwcNeeded > pLineBuf->cwcBufAlloc)
     5779            {
     5780                void *pvNew;
     5781                KU32  cwcNew = !pLineBuf->cwcBufAlloc ? 1024 : pLineBuf->cwcBufAlloc * 2;
     5782                while (cwcNew < cwcNeeded)
     5783                    cwcNew *= 2;
     5784                pvNew = kHlpRealloc(pLineBuf->pwcBuf, cwcNew * sizeof(wchar_t));
     5785                if (pvNew)
     5786                {
     5787                    pLineBuf->pwcBuf = (wchar_t *)pvNew;
     5788                    pLineBuf->cwcBufAlloc = cwcNew;
     5789                }
     5790                else
     5791                {
     5792                    pvNew = kHlpRealloc(pLineBuf->pwcBuf, cwcNeeded * sizeof(wchar_t));
     5793                    if (pvNew)
     5794                    {
     5795                        pLineBuf->pwcBuf = (wchar_t *)pvNew;
     5796                        pLineBuf->cwcBufAlloc = cwcNeeded;
     5797                    }
     5798                    else
     5799                    {
     5800                        /* This isn't perfect, but it will have to do for now. */
     5801                        if (pLineBuf->cwcBuf > 0)
     5802                        {
     5803                            kwSandboxConsoleAddToCombined(pSandbox, pLineBuf->pwcBuf, pLineBuf->cwcBuf, K_TRUE /*fBrokenLine*/);
     5804                            pLineBuf->cwcBuf = 0;
     5805                        }
     5806                        kwSandboxConsoleAddToCombined(pSandbox, pwcBuffer, cwcToWrite, K_TRUE /*fBrokenLine*/);
     5807                        return;
     5808                    }
     5809                }
     5810            }
     5811
     5812            /*
     5813             * Handle the case where we only add to the line buffer.
     5814             */
     5815            if (offLastIncompleteLine == 0)
     5816            {
     5817                memcpy(&pLineBuf->pwcBuf[pLineBuf->cwcBuf], pwcBuffer, cwcToWrite * sizeof(wchar_t));
     5818                pLineBuf->cwcBuf += cwcToWrite;
     5819                return;
     5820            }
     5821        }
     5822
     5823        /*
     5824         * If there is sufficient combined buffer to handle this request, this are rather simple.
     5825         */
     5826        if (pLineBuf->cwcBuf + cchLastIncompleteLine <= K_ELEMENTS(pSandbox->Combined.wszBuf))
     5827        {
     5828            if (pLineBuf->cwcBuf > 0)
     5829            {
     5830                memcpy(&pSandbox->Combined.wszBuf[pSandbox->Combined.cwcBuf],
     5831                       pLineBuf->pwcBuf, pLineBuf->cwcBuf * sizeof(wchar_t));
     5832                pSandbox->Combined.cwcBuf += pLineBuf->cwcBuf;
     5833                pLineBuf->cwcBuf = 0;
     5834            }
     5835
     5836            memcpy(&pSandbox->Combined.wszBuf[pSandbox->Combined.cwcBuf],
     5837                   pwcBuffer, offLastIncompleteLine * sizeof(wchar_t));
     5838            pSandbox->Combined.cwcBuf += offLastIncompleteLine;
     5839        }
     5840        else
     5841        {
     5842            /*
     5843             * Do line-by-line processing of the input, flusing the combined buffer
     5844             * when it becomes necessary.  We may have to write lines
     5845             */
     5846            KU32 off = 0;
     5847            KU32 offNextLine = 0;
     5848
     5849            /* If there is buffered chars, we handle the first line outside the
     5850               main loop.  We must try our best outputting it as a complete line. */
     5851            if (pLineBuf->cwcBuf > 0)
     5852            {
     5853                while (offNextLine < cwcToWrite && pwcBuffer[offNextLine] != '\n')
     5854                    offNextLine++;
     5855                offNextLine++;
     5856                kHlpAssert(offNextLine <= offLastIncompleteLine);
     5857
     5858                if (pLineBuf->cwcBuf + offNextLine + pSandbox->Combined.cwcBuf <= K_ELEMENTS(pSandbox->Combined.wszBuf))
     5859                {
     5860                    memcpy(&pSandbox->Combined.wszBuf[pSandbox->Combined.cwcBuf],
     5861                           pLineBuf->pwcBuf, pLineBuf->cwcBuf * sizeof(wchar_t));
     5862                    pSandbox->Combined.cwcBuf += pLineBuf->cwcBuf;
     5863                    pLineBuf->cwcBuf = 0;
     5864
     5865                    memcpy(&pSandbox->Combined.wszBuf[pSandbox->Combined.cwcBuf], pwcBuffer, offNextLine * sizeof(wchar_t));
     5866                    pSandbox->Combined.cwcBuf += offNextLine;
     5867                }
     5868                else
     5869                {
     5870                    KU32 cwcLeft = pLineBuf->cwcBufAlloc - pLineBuf->cwcBuf;
     5871                    if (cwcLeft > 0)
     5872                    {
     5873                        KU32 cwcCopy = K_MIN(cwcLeft, offNextLine);
     5874                        memcpy(&pLineBuf->pwcBuf[pLineBuf->cwcBuf], pwcBuffer, cwcCopy * sizeof(wchar_t));
     5875                        pLineBuf->cwcBuf += cwcCopy;
     5876                        off += cwcCopy;
     5877                    }
     5878                    if (pLineBuf->cwcBuf > 0)
     5879                    {
     5880                        kwSandboxConsoleAddToCombined(pSandbox, pLineBuf->pwcBuf, pLineBuf->cwcBuf, K_TRUE /*fBrokenLine*/);
     5881                        pLineBuf->cwcBuf = 0;
     5882                    }
     5883                    if (off < offNextLine)
     5884                        kwSandboxConsoleAddToCombined(pSandbox, &pwcBuffer[off], offNextLine - off, K_TRUE /*fBrokenLine*/);
     5885                }
     5886                off = offNextLine;
     5887            }
     5888
     5889            /* Deal with the remaining lines */
     5890            while (off < offLastIncompleteLine)
     5891            {
     5892                while (offNextLine < offLastIncompleteLine && pwcBuffer[offNextLine] != '\n')
     5893                    offNextLine++;
     5894                offNextLine++;
     5895                kHlpAssert(offNextLine <= offLastIncompleteLine);
     5896                kwSandboxConsoleAddToCombined(pSandbox, &pwcBuffer[off], offNextLine - off, K_FALSE /*fBrokenLine*/);
     5897                off = offNextLine;
     5898            }
     5899        }
     5900
     5901        /*
     5902         * Buffer any remaining incomplete line chars.
     5903         */
     5904        if (offLastIncompleteLine < cwcToWrite)
     5905        {
     5906            memcpy(&pLineBuf->pwcBuf, &pwcBuffer[offLastIncompleteLine], cchLastIncompleteLine * sizeof(wchar_t));
     5907            pLineBuf->cwcBuf = cchLastIncompleteLine;
     5908        }
     5909    }
     5910}
     5911
     5912
     5913/**
     5914 * Worker for WriteConsoleA and WriteFile.
     5915 *
     5916 * @param   pSandbox            The sandbox.
     5917 * @param   pLineBuf            The line buffer.
     5918 * @param   pchBuffer           What to write.
     5919 * @param   cchToWrite          How much to write.
     5920 */
     5921static void kwSandboxConsoleWriteA(PKWSANDBOX pSandbox, PKWCONSOLEOUTPUTLINE pLineBuf, const char *pchBuffer, KU32 cchToWrite)
     5922{
     5923    /*
     5924     * Convert it to wide char and use the 'W' to do the work.
     5925     */
     5926    int         cwcRet;
     5927    KU32        cwcBuf = cchToWrite * 2 + 1;
     5928    wchar_t    *pwcBufFree = NULL;
     5929    wchar_t    *pwcBuf;
     5930
     5931    if (cwcBuf <= 4096)
     5932        pwcBuf = alloca(cwcBuf * sizeof(wchar_t));
     5933    else
     5934        pwcBuf = pwcBufFree = kHlpAlloc(cwcBuf * sizeof(wchar_t));
     5935
     5936    cwcRet = MultiByteToWideChar(pSandbox->Combined.uCodepage, 0/*dwFlags*/, pchBuffer, cchToWrite, pwcBuf, cwcBuf);
     5937    if (cwcRet > 0)
     5938         kwSandboxConsoleWriteW(pSandbox, pLineBuf, pwcBuf, cwcRet);
     5939    else
     5940    {
     5941        DWORD cchWritten;
     5942        kHlpAssertFailed();
     5943
     5944        /* Flush the line buffer and combined buffer before calling WriteConsoleA. */
     5945        if (pLineBuf->cwcBuf > 0)
     5946        {
     5947            kwSandboxConsoleAddToCombined(pSandbox, pLineBuf->pwcBuf, pLineBuf->cwcBuf, K_TRUE /*fBroken*/);
     5948            pLineBuf->cwcBuf = 0;
     5949        }
     5950        kwSandboxConsoleFlushCombined(pSandbox);
     5951
     5952        if (WriteConsoleA(pLineBuf->hBackup, pchBuffer, cchToWrite, &cchWritten, NULL /*pvReserved*/))
     5953        {
     5954            if (cchWritten >= cchToWrite)
     5955            { /* likely */ }
     5956            else
     5957            {
     5958                KU32 off = 0;
     5959                do
     5960                {
     5961                    off += cchWritten;
     5962                    cchWritten = 0;
     5963                } while (   off < cchToWrite
     5964                         && WriteConsoleA(pLineBuf->hBackup, &pchBuffer[off], cchToWrite - off, &cchWritten, NULL));
     5965            }
     5966        }
     5967    }
     5968
     5969    if (pwcBufFree)
     5970        kHlpFree(pwcBufFree);
     5971}
     5972
     5973
     5974/** Kernel32 - WriteConsoleA  */
     5975BOOL WINAPI kwSandbox_Kernel32_WriteConsoleA(HANDLE hConOutput, CONST VOID *pvBuffer, DWORD cbToWrite, PDWORD pcbWritten,
     5976                                             PVOID pvReserved)
     5977{
     5978    BOOL                    fRc;
     5979    PKWCONSOLEOUTPUTLINE    pLineBuf;
     5980
     5981    if (hConOutput == g_Sandbox.StdErr.hOutput)
     5982        pLineBuf = &g_Sandbox.StdErr;
     5983    else
     5984        pLineBuf = &g_Sandbox.StdOut;
     5985    if (pLineBuf->fIsConsole)
     5986    {
     5987        kwSandboxConsoleWriteA(&g_Sandbox, pLineBuf, (char const *)pvBuffer, cbToWrite);
     5988
     5989        KWFS_LOG(("WriteConsoleA: %p, %p LB %#x (%*.*s), %p, %p -> TRUE [cached]\n",
     5990                  hConOutput, pvBuffer, cbToWrite, cbToWrite, cbToWrite, pvBuffer, pcbWritten, pvReserved));
     5991        if (pcbWritten)
     5992            *pcbWritten = cbToWrite;
     5993        fRc = TRUE;
     5994    }
     5995    else
     5996    {
     5997        fRc = WriteConsoleA(hConOutput, pvBuffer, cbToWrite, pcbWritten, pvReserved);
     5998        KWFS_LOG(("WriteConsoleA: %p, %p LB %#x (%*.*s), %p, %p -> %d !fallback!\n",
     5999                  hConOutput, pvBuffer, cbToWrite, cbToWrite, cbToWrite, pvBuffer, pcbWritten, pvReserved, fRc));
     6000    }
     6001    return fRc;
     6002}
     6003
     6004
     6005/** Kernel32 - WriteConsoleW  */
     6006BOOL WINAPI kwSandbox_Kernel32_WriteConsoleW(HANDLE hConOutput, CONST VOID *pvBuffer, DWORD cwcToWrite, PDWORD pcwcWritten,
     6007                                             PVOID pvReserved)
     6008{
     6009    BOOL                    fRc;
     6010    PKWCONSOLEOUTPUTLINE    pLineBuf;
     6011
     6012    if (hConOutput == g_Sandbox.StdErr.hOutput)
     6013        pLineBuf = &g_Sandbox.StdErr;
     6014    else
     6015        pLineBuf = &g_Sandbox.StdOut;
     6016    if (pLineBuf->fIsConsole)
     6017    {
     6018        kwSandboxConsoleWriteW(&g_Sandbox, pLineBuf, (wchar_t const *)pvBuffer, cwcToWrite);
     6019
     6020        KWFS_LOG(("WriteConsoleW: %p, %p LB %#x (%*.*ls), %p, %p -> TRUE [cached]\n",
     6021                  hConOutput, pvBuffer, cwcToWrite, cwcToWrite, cwcToWrite, pvBuffer, pcwcWritten, pvReserved));
     6022        if (pcwcWritten)
     6023            *pcwcWritten = cwcToWrite;
     6024        fRc = TRUE;
     6025    }
     6026    else
     6027    {
     6028        fRc = WriteConsoleW(hConOutput, pvBuffer, cwcToWrite, pcwcWritten, pvReserved);
     6029        KWFS_LOG(("WriteConsoleW: %p, %p LB %#x (%*.*ls), %p, %p -> %d !fallback!\n",
     6030                  hConOutput, pvBuffer, cwcToWrite, cwcToWrite, cwcToWrite, pvBuffer, pcwcWritten, pvReserved, fRc));
     6031    }
     6032    return fRc;
     6033}
     6034
     6035#endif /* WITH_CONSOLE_OUTPUT_BUFFERING */
    55016036
    55026037
     
    61276662#endif
    61286663
     6664    { TUPLE("WriteConsoleA"),               NULL,       (KUPTR)kwSandbox_Kernel32_WriteConsoleA },
     6665    { TUPLE("WriteConsoleW"),               NULL,       (KUPTR)kwSandbox_Kernel32_WriteConsoleW },
     6666
    61296667    { TUPLE("VirtualAlloc"),                NULL,       (KUPTR)kwSandbox_Kernel32_VirtualAlloc },
    61306668    { TUPLE("VirtualFree"),                 NULL,       (KUPTR)kwSandbox_Kernel32_VirtualFree },
     
    62416779    { TUPLE("SetConsoleCtrlHandler"),       NULL,       (KUPTR)kwSandbox_Kernel32_SetConsoleCtrlHandler },
    62426780
     6781    { TUPLE("WriteConsoleA"),               NULL,       (KUPTR)kwSandbox_Kernel32_WriteConsoleA },
     6782    { TUPLE("WriteConsoleW"),               NULL,       (KUPTR)kwSandbox_Kernel32_WriteConsoleW },
     6783
    62436784#ifdef WITH_HASH_MD5_CACHE
    62446785    { TUPLE("CryptCreateHash"),             NULL,       (KUPTR)kwSandbox_Advapi32_CryptCreateHash },
     
    65537094    pSandbox->pgmptr        = (char *)pTool->pszPath;
    65547095    pSandbox->wpgmptr       = (wchar_t *)pTool->pwszPath;
     7096#ifdef WITH_CONSOLE_OUTPUT_BUFFERING
     7097    pSandbox->StdOut.cwcBuf = 0;
     7098    pSandbox->StdErr.cwcBuf = 0;
     7099    pSandbox->Combined.cwcBuf = 0;
     7100    pSandbox->Combined.cFlushes = 0;
     7101#endif
    65557102    pSandbox->cArgs         = cArgs;
    65567103    pSandbox->papszArgs     = (char **)papszArgs;
     
    68857432            rcExit = 42 + 4;
    68867433
    6887         /* Clean up essential bits only, the rest is done after we've replied to kmk. */
     7434        /*
     7435         * Flush and clean up the essential bits only, postpone whatever we
     7436         * can till after we've replied to kmk.
     7437         */
     7438#ifdef WITH_CONSOLE_OUTPUT_BUFFERING
     7439        kwSandboxConsoleFlushAll(&g_Sandbox);
     7440#endif
    68887441        kwSandboxCleanup(&g_Sandbox);
    68897442    }
     
    73767929    PVOID           pvVecXcptHandler = AddVectoredExceptionHandler(0 /*called last*/, kwSandboxVecXcptEmulateChained);
    73777930#endif
     7931#ifdef WITH_CONSOLE_OUTPUT_BUFFERING
     7932    HANDLE                          hCurProc       = GetCurrentProcess();
     7933    PPEB                            pPeb           = kwSandboxGetProcessEnvironmentBlock();
     7934    PMY_RTL_USER_PROCESS_PARAMETERS pProcessParams = (PMY_RTL_USER_PROCESS_PARAMETERS)pPeb->ProcessParameters;
     7935#endif
    73787936
    73797937    /*
     
    73997957    if (pszTmp && *pszTmp != '\0')
    74007958        kFsCacheSetupCustomRevisionForTree(g_pFsCache, kFsCacheLookupA(g_pFsCache, pszTmp, &enmIgnored));
     7959
     7960#ifdef WITH_CONSOLE_OUTPUT_BUFFERING
     7961    /*
     7962     * Get and duplicate the console handles.
     7963     */
     7964    g_Sandbox.StdOut.hOutput = pProcessParams->StandardOutput;
     7965    if (!DuplicateHandle(hCurProc, pProcessParams->StandardOutput, hCurProc, &g_Sandbox.StdOut.hBackup,
     7966                         GENERIC_WRITE, FALSE /*fInherit*/, DUPLICATE_SAME_ACCESS))
     7967        kHlpAssertFailedStmt(g_Sandbox.StdOut.hBackup = pProcessParams->StandardOutput);
     7968    g_Sandbox.StdOut.fIsConsole = GetFileType(g_Sandbox.StdOut.hOutput) == FILE_TYPE_CHAR;
     7969
     7970    g_Sandbox.StdErr.hOutput = pProcessParams->StandardError;
     7971    if (!DuplicateHandle(hCurProc, pProcessParams->StandardError, hCurProc, &g_Sandbox.StdErr.hBackup,
     7972                         GENERIC_WRITE, FALSE /*fInherit*/, DUPLICATE_SAME_ACCESS))
     7973        kHlpAssertFailedStmt(g_Sandbox.StdErr.hBackup = pProcessParams->StandardError);
     7974    g_Sandbox.StdErr.fIsConsole = GetFileType(g_Sandbox.StdErr.hOutput) == FILE_TYPE_CHAR;
     7975
     7976    if (g_Sandbox.StdErr.fIsConsole)
     7977    {
     7978        g_Sandbox.Combined.hOutput   = g_Sandbox.StdErr.hBackup;
     7979        g_Sandbox.Combined.uCodepage = GetConsoleCP();
     7980    }
     7981    else if (g_Sandbox.StdOut.fIsConsole)
     7982    {
     7983        g_Sandbox.Combined.hOutput   = g_Sandbox.StdOut.hBackup;
     7984        g_Sandbox.Combined.uCodepage = GetConsoleCP();
     7985    }
     7986    else
     7987    {
     7988        g_Sandbox.Combined.hOutput   = INVALID_HANDLE_VALUE;
     7989        g_Sandbox.Combined.uCodepage = CP_ACP;
     7990    }
     7991#endif
     7992
    74017993
    74027994    /*
Note: See TracChangeset for help on using the changeset viewer.