Changeset 2900 in kBuild
- Timestamp:
- Sep 9, 2016 2:42:06 PM (9 years ago)
- Location:
- trunk/src
- Files:
-
- 2 added
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kWorker/kWorker.c
r2898 r2900 69 69 * they are included. */ 70 70 #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 71 76 72 77 … … 276 281 typedef KFSWCACHEDFILE *PKFSWCACHEDFILE; 277 282 278 279 283 #ifdef WITH_HASH_MD5_CACHE 284 280 285 /** Pointer to a MD5 hash instance. */ 281 286 typedef struct KWHASHMD5 *PKWHASHMD5; … … 307 312 /** Magic value for KWHASHMD5::uMagic (Les McCann). */ 308 313 # define KWHASHMD5_MAGIC KUPTR_C(0x19350923) 314 309 315 #endif /* WITH_HASH_MD5_CACHE */ 310 311 316 #ifdef WITH_TEMP_MEMORY_FILES 312 317 313 318 typedef struct KWFSTEMPFILESEG *PKWFSTEMPFILESEG; … … 345 350 } KWFSTEMPFILE; 346 351 352 #endif /* WITH_TEMP_MEMORY_FILES */ 353 #ifdef WITH_CONSOLE_OUTPUT_BUFFERING 354 355 /** 356 * Console line buffer. 357 */ 358 typedef 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. */ 374 typedef KWCONSOLEOUTPUTLINE *PKWCONSOLEOUTPUTLINE; 375 376 /** 377 * Combined console buffer of complete lines. 378 */ 379 typedef 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. */ 395 typedef KWCONSOLEOUTPUT *PKWCONSOLEOUTPUT; 396 397 #endif /* WITH_CONSOLE_OUTPUT_BUFFERING */ 347 398 348 399 /** Handle type. */ … … 554 605 } LastHashRead; 555 606 #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 556 616 } KWSANDBOX; 557 617 … … 640 700 static int kwLdrModuleResolveAndLookup(const char *pszName, PKWMODULE pExe, PKWMODULE pImporter, PKWMODULE *ppMod); 641 701 static KBOOL kwSandboxHandleTableEnter(PKWSANDBOX pSandbox, PKWHANDLE pHandle); 702 #ifdef WITH_CONSOLE_OUTPUT_BUFFERING 703 static void kwSandboxConsoleWriteA(PKWSANDBOX pSandbox, PKWCONSOLEOUTPUTLINE pLineBuf, const char *pchBuffer, KU32 cchToWrite); 704 #endif 642 705 643 706 … … 5013 5076 } 5014 5077 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 5015 5095 KWFS_LOG(("WriteFile(%p)\n", hFile)); 5016 5096 return WriteFile(hFile, pvBuffer, cbToWrite, pcbActuallyWritten, pOverlapped); … … 5499 5579 } 5500 5580 #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 */ 5600 static 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 */ 5634 static 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 */ 5653 static 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 */ 5676 static 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 */ 5707 static 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 */ 5758 static 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 */ 5921 static 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 */ 5975 BOOL 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 */ 6006 BOOL 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 */ 5501 6036 5502 6037 … … 6127 6662 #endif 6128 6663 6664 { TUPLE("WriteConsoleA"), NULL, (KUPTR)kwSandbox_Kernel32_WriteConsoleA }, 6665 { TUPLE("WriteConsoleW"), NULL, (KUPTR)kwSandbox_Kernel32_WriteConsoleW }, 6666 6129 6667 { TUPLE("VirtualAlloc"), NULL, (KUPTR)kwSandbox_Kernel32_VirtualAlloc }, 6130 6668 { TUPLE("VirtualFree"), NULL, (KUPTR)kwSandbox_Kernel32_VirtualFree }, … … 6241 6779 { TUPLE("SetConsoleCtrlHandler"), NULL, (KUPTR)kwSandbox_Kernel32_SetConsoleCtrlHandler }, 6242 6780 6781 { TUPLE("WriteConsoleA"), NULL, (KUPTR)kwSandbox_Kernel32_WriteConsoleA }, 6782 { TUPLE("WriteConsoleW"), NULL, (KUPTR)kwSandbox_Kernel32_WriteConsoleW }, 6783 6243 6784 #ifdef WITH_HASH_MD5_CACHE 6244 6785 { TUPLE("CryptCreateHash"), NULL, (KUPTR)kwSandbox_Advapi32_CryptCreateHash }, … … 6553 7094 pSandbox->pgmptr = (char *)pTool->pszPath; 6554 7095 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 6555 7102 pSandbox->cArgs = cArgs; 6556 7103 pSandbox->papszArgs = (char **)papszArgs; … … 6885 7432 rcExit = 42 + 4; 6886 7433 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 6888 7441 kwSandboxCleanup(&g_Sandbox); 6889 7442 } … … 7376 7929 PVOID pvVecXcptHandler = AddVectoredExceptionHandler(0 /*called last*/, kwSandboxVecXcptEmulateChained); 7377 7930 #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 7378 7936 7379 7937 /* … … 7399 7957 if (pszTmp && *pszTmp != '\0') 7400 7958 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 7401 7993 7402 7994 /* -
trunk/src/kmk/kmkbuiltin/cat.c
r2113 r2900 81 81 82 82 83 #ifdef KBUILD_OS_WINDOWS 84 /* This is a trick to seriuosly speed up console output windows. */ 85 # undef write 86 # define write maybe_con_write 87 extern ssize_t maybe_con_write(int, void const *, size_t); 88 #endif 89 90 83 91 int bflag, eflag, nflag, sflag, tflag, vflag; 84 92 /*int rval;*/ … … 120 128 #ifdef kmk_builtin_cat /* kmk did this already. */ 121 129 setlocale(LC_CTYPE, ""); 130 #else 131 fflush(stdout); 122 132 #endif 123 133 … … 288 298 raw_cat(int rfd) 289 299 { 290 int off, wfd ;300 int off, wfd = fileno(stdout); 291 301 ssize_t nr, nw; 292 302 static size_t bsize; … … 298 308 if (fstat(wfd, &sbuf)) 299 309 return err(1, "%s", filename); 300 #ifdef _MSC_VER301 bsize = 1 024;310 #ifdef KBUILD_OS_WINDOWS 311 bsize = 16384; 302 312 #else 303 313 bsize = MAX(sbuf.st_blksize, 1024); -
trunk/src/kmk/kmkbuiltin/printf.c
r2646 r2900 76 76 #include "../kmkbuiltin.h" 77 77 78 #ifdef KBUILD_OS_WINDOWS 79 /* This is a trick to speed up console output on windows. */ 80 # undef fwrite 81 # define fwrite maybe_con_fwrite 82 extern size_t maybe_con_fwrite(void const *, size_t, size_t, FILE *); 83 #endif 84 78 85 79 86 #ifdef __GNUC__ … … 113 120 static int usage(FILE *); 114 121 122 static int flush_buffer(void); 115 123 static void b_count(int); 116 124 static void b_output(int); … … 126 134 #include "../../bin/sh/bltin/bltin.h" 127 135 #endif /* SHELL */ 136 137 /* Buffer the output because windows doesn't do line buffering of stdout. */ 138 static char g_achBuf[256]; 139 static size_t g_cchBuf; 128 140 129 141 #define PF(f, func) { \ … … 156 168 int ch; 157 169 158 /* kmk: reset getopt and set progname*/170 /* kmk: reset getopt, set progname and reset buffer. */ 159 171 g_progname = argv[0]; 160 172 opterr = 1; … … 225 237 rval = 0; 226 238 gargv = NULL; 239 g_cchBuf = 0; 227 240 228 241 format = *argv; … … 272 285 ch = *fmt; 273 286 if (!ch) { 287 flush_buffer(); 274 288 warnx("missing format character"); 275 289 return (1); … … 354 368 } 355 369 default: 370 flush_buffer(); 356 371 warnx("%s: invalid directive", start); 357 372 return 1; … … 360 375 *fmt = nextch; 361 376 /* escape if a \c was encountered */ 362 if (rval & 0x100) 377 if (rval & 0x100) { 378 flush_buffer(); 363 379 return rval & ~0x100; 380 } 364 381 } 365 382 } while (gargv != argv && *gargv); 366 383 384 flush_buffer(); 367 385 return rval; 368 386 } 387 369 388 370 389 /* helper functions for conv_escape_str */ … … 408 427 } 409 428 #endif 410 return putchar(ch); 429 /* Buffered output. */ 430 if (g_cchBuf + 1 < sizeof(g_achBuf)) { 431 g_achBuf[g_cchBuf++] = ch; 432 } else { 433 int rc = flush_buffer(); 434 g_achBuf[g_cchBuf++] = ch; 435 if (rc) 436 return -1; 437 } 438 return 0; 411 439 } 412 440 413 441 static int wrap_printf(const char * fmt, ...) 414 442 { 415 int rc;443 ssize_t cchRet; 416 444 va_list va; 417 445 char *pszTmp; 446 447 va_start(va, fmt); 448 cchRet = vasprintf(&pszTmp, fmt, va); 449 va_end(va); 450 if (cchRet >= 0) { 418 451 #ifndef kmk_builtin_printf 419 if (g_o) { 420 char *str; 421 422 va_start(va, fmt); 423 rc = vasprintf(&str, fmt, va); 424 va_end(va); 425 if (rc >= 0) { 426 g_o = variable_buffer_output(g_o, str, rc); 427 free(str); 428 } 429 return rc; 430 } 431 #endif 432 433 va_start(va, fmt); 434 rc = vprintf(fmt, va); 435 va_end(va); 436 return rc; 437 } 452 if (g_o) { 453 g_o = variable_buffer_output(g_o, pszTmp, cchRet); 454 } else 455 #endif 456 { 457 if (cchRet + g_cchBuf <= sizeof(g_achBuf)) { 458 /* We've got space in the buffer. */ 459 memcpy(&g_achBuf[g_cchBuf], pszTmp, cchRet); 460 g_cchBuf += cchRet; 461 } else { 462 /* Try write out complete lines. */ 463 const char *pszLeft = pszTmp; 464 ssize_t cchLeft = cchRet; 465 466 while (cchLeft > 0) { 467 const char *pchNewLine = strchr(pszLeft, '\n'); 468 ssize_t cchLine = pchNewLine ? pchNewLine - pszLeft + 1 : cchLeft; 469 if (g_cchBuf + cchLine <= sizeof(g_achBuf)) { 470 memcpy(&g_achBuf[g_cchBuf], pszLeft, cchLine); 471 g_cchBuf += cchLine; 472 } else { 473 if (flush_buffer() < 0) { 474 return -1; 475 } 476 if (fwrite(pszLeft, cchLine, 1, stdout) < 1) { 477 return -1; 478 } 479 } 480 pszLeft += cchLine; 481 cchLeft -= cchLine; 482 } 483 } 484 } 485 free(pszTmp); 486 } 487 return (int)cchRet; 488 } 489 490 /** 491 * Flushes the g_abBuf/g_cchBuf. 492 */ 493 static int flush_buffer(void) 494 { 495 if (g_cchBuf > 0) { 496 ssize_t cchToWrite = g_cchBuf; 497 ssize_t cchWritten = fwrite(g_achBuf, 1, g_cchBuf, stdout); 498 g_cchBuf = 0; 499 if (cchWritten >= cchToWrite) { 500 /* likely */ 501 } else { 502 ssize_t off = cchWritten; 503 if (cchWritten >= 0) { 504 off = cchWritten; 505 } else if (errno == EINTR) { 506 cchWritten = 0; 507 } else { 508 return -1; 509 } 510 511 while (off < cchToWrite) { 512 cchWritten = fwrite(&g_achBuf[off], 1, cchToWrite - off, stdout); 513 if (cchWritten > 0) { 514 off += cchWritten; 515 } else if (errno == EINTR) { 516 /* nothing */ 517 } else { 518 return -1; 519 } 520 } 521 } 522 } 523 return 0; 524 } 525 438 526 439 527 -
trunk/src/kmk/main.c
r2818 r2900 1380 1380 char *windows32_path = NULL; 1381 1381 1382 # ifndef ELECTRIC_HEAP /* Drop this because it prevents JIT debugging. */1382 # ifndef ELECTRIC_HEAP /* Drop this because it prevents JIT debugging. */ 1383 1383 SetUnhandledExceptionFilter(handle_runtime_exceptions); 1384 # endif /* !ELECTRIC_HEAP */1384 # endif /* !ELECTRIC_HEAP */ 1385 1385 1386 1386 /* start off assuming we have no shell */ -
trunk/src/lib/Makefile.kmk
r2886 r2900 39 39 crc32.c \ 40 40 md5.c \ 41 maybe_con_write.c \ 42 maybe_con_fwrite.c \ 41 43 kbuild_version.c 42 44 kUtil_SOURCES.win = \ -
trunk/src/lib/nt/ntstuff.h
r2862 r2900 74 74 } MY_STRING; 75 75 typedef MY_STRING MY_ANSI_STRING; 76 77 typedef struct MY_CURDIR 78 { 79 UNICODE_STRING DosPath; 80 HANDLE Handle; 81 } MY_CURDIR; 82 typedef MY_CURDIR *PMY_CURDIR; 83 84 typedef struct MY_RTL_DRIVE_LETTER_CURDIR 85 { 86 USHORT Flags; 87 USHORT Length; 88 ULONG TimeStamp; 89 MY_ANSI_STRING DosPath; 90 } MY_RTL_DRIVE_LETTER_CURDIR; 91 typedef MY_RTL_DRIVE_LETTER_CURDIR *PRTL_DRIVE_LETTER_CURDIR; 92 93 typedef struct MY_RTL_USER_PROCESS_PARAMETERS 94 { 95 ULONG MaximumLength; 96 ULONG Length; 97 ULONG Flags; 98 ULONG DebugFlags; 99 HANDLE ConsoleHandle; 100 ULONG ConsoleFlags; 101 HANDLE StandardInput; 102 HANDLE StandardOutput; 103 HANDLE StandardError; 104 MY_CURDIR CurrentDirectory; 105 MY_UNICODE_STRING DllPath; 106 MY_UNICODE_STRING ImagePathName; 107 MY_UNICODE_STRING CommandLine; 108 PWSTR Environment; 109 ULONG StartingX; 110 ULONG StartingY; 111 ULONG CountX; 112 ULONG CountY; 113 ULONG CountCharsX; 114 ULONG CountCharsY; 115 ULONG FillAttribute; 116 ULONG WindowFlags; 117 ULONG ShowWindowFlags; 118 MY_UNICODE_STRING WindowTitle; 119 MY_UNICODE_STRING DesktopInfo; 120 MY_UNICODE_STRING ShellInfo; 121 MY_UNICODE_STRING RuntimeInfo; 122 MY_RTL_DRIVE_LETTER_CURDIR CurrentDirectories[0x20]; 123 SIZE_T EnvironmentSize; /* >= Vista+ */ 124 SIZE_T EnvironmentVersion; /* >= Windows 7. */ 125 PVOID PackageDependencyData; /* >= Windows 8 or Windows 8.1. */ 126 ULONG ProcessGroupId; /* >= Windows 8 or Windows 8.1. */ 127 } MY_RTL_USER_PROCESS_PARAMETERS; 128 typedef MY_RTL_USER_PROCESS_PARAMETERS *PMY_RTL_USER_PROCESS_PARAMETERS; 76 129 77 130 typedef struct MY_OBJECT_ATTRIBUTES
Note:
See TracChangeset
for help on using the changeset viewer.