VirtualBox

Changeset 95083 in vbox for trunk/src/VBox/Runtime/r3/win


Ignore:
Timestamp:
May 24, 2022 8:46:07 PM (3 years ago)
Author:
vboxsync
Message:

IPRT/pipe/win: Added workaround to RTPipeQueryReadable for XP and older where PeekNamedPipe could return a too high value for what's available to read. Seems this issue was addressed in some XP service pack (1?).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/win/pipe-win.cpp

    r93115 r95083  
    3838#include <iprt/critsect.h>
    3939#include <iprt/err.h>
     40#include <iprt/log.h>
    4041#include <iprt/mem.h>
    4142#include <iprt/string.h>
     
    12031204        return rc;
    12041205
     1206    /** @todo The file size should give the same info and be slightly faster... */
    12051207    DWORD cbAvailable = 0;
    12061208    if (PeekNamedPipe(pThis->hPipe, NULL, 0, NULL, &cbAvailable, NULL))
     1209    {
     1210#if ARCH_BITS == 32
     1211        /*
     1212         * Kludge!
     1213         *
     1214         * Prior to XP SP1 (?), the returned cbAvailable value was not adjusted
     1215         * by read position in the current message/buffer, so it could
     1216         * potentially be too high.  This could cause the caller to try read
     1217         * more data than what's actually available, which may cause the read
     1218         * to block when the caller thought it wouldn't.
     1219         *
     1220         * To get the accurate size, we have to provide and output buffer
     1221         * and see how much we actually get back in it, as the data peeking
     1222         * works correctly (as you would expect).
     1223         */
     1224        if (cbAvailable == 0 || g_enmWinVer >= kRTWinOSType_XP64)
     1225        { /* No data available or kernel shouldn't be affected. */ }
     1226        else
     1227        {
     1228            for (unsigned i = 0; ; i++)
     1229            {
     1230                uint8_t abBufStack[_16K];
     1231                void   *pvBufFree = NULL;
     1232                void   *pvBuf;
     1233                DWORD   cbBuf     = RT_ALIGN_32(cbAvailable + i * 256, 64);
     1234                if (cbBuf <= sizeof(abBufStack))
     1235                {
     1236                    pvBuf = abBufStack;
     1237                    /* No cbBuf = sizeof(abBufStack) here! PeekNamedPipe bounce buffers the request on the heap. */
     1238                }
     1239                else
     1240                {
     1241                    pvBufFree = pvBuf = RTMemTmpAlloc(cbBuf);
     1242                    if (!pvBuf)
     1243                    {
     1244                        rc = VERR_NO_TMP_MEMORY;
     1245                        cbAvailable = 1;
     1246                        break;
     1247                    }
     1248                }
     1249
     1250                DWORD cbAvailable2 = 0;
     1251                DWORD cbRead       = 0;
     1252                BOOL fRc = PeekNamedPipe(pThis->hPipe, pvBuf, cbBuf, &cbRead, &cbAvailable2, NULL);
     1253                Log(("RTPipeQueryReadable: #%u: cbAvailable=%#x cbRead=%#x cbAvailable2=%#x (cbBuf=%#x)\n",
     1254                     i, cbAvailable, cbRead, cbAvailable2, cbBuf));
     1255
     1256                RTMemTmpFree(pvBufFree);
     1257
     1258                if (fRc)
     1259                {
     1260                    if (cbAvailable2 <= cbBuf || i >= 10)
     1261                        cbAvailable = cbRead;
     1262                    else
     1263                    {
     1264                        cbAvailable = cbAvailable2;
     1265                        continue;
     1266                    }
     1267                }
     1268                else
     1269                {
     1270                    rc = RTErrConvertFromWin32(GetLastError());
     1271                    cbAvailable = 1;
     1272                }
     1273                break;
     1274            }
     1275        }
     1276#endif
    12071277        *pcbReadable = cbAvailable;
     1278    }
    12081279    else
    12091280        rc = RTErrConvertFromWin32(GetLastError());
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette