VirtualBox

Changeset 57620 in vbox


Ignore:
Timestamp:
Sep 4, 2015 10:08:46 AM (9 years ago)
Author:
vboxsync
Message:

fileio-win.cpp: Condensed the console I/O handle workaround code in RTFileQueryInfo and added GetFileType as a fallback.

File:
1 edited

Legend:

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

    r57603 r57620  
    3636
    3737#include <iprt/file.h>
     38
     39#include <iprt/asm.h>
     40#include <iprt/assert.h>
    3841#include <iprt/path.h>
    39 #include <iprt/assert.h>
    4042#include <iprt/string.h>
    4143#include <iprt/err.h>
     
    831833    if (!GetFileInformationByHandle(hHandle, &Data))
    832834    {
     835        /*
     836         * Console I/O handles make trouble here.  On older windows versions they
     837         * end up with ERROR_INVALID_HANDLE when handed to the above API, while on
     838         * more recent ones they cause different errors to appear.
     839         *
     840         * Thus, we must ignore the latter and doubly verify invalid handle claims.
     841         * We use the undocumented VerifyConsoleIoHandle to do this, falling back on
     842         * GetFileType should it not be there.
     843         */
    833844        DWORD dwErr = GetLastError();
    834         /* Only return if we *really* don't have a valid handle value,
    835          * everything else is fine here ... */
    836845        if (dwErr == ERROR_INVALID_HANDLE)
    837846        {
    838             /*
    839              * On Windows 7 or earlier certain standard handles such as
    840              * stdin, stdout and stderr were ring-3 pseudo handles which the
    841              * kernel didn't know about.
    842              *
    843              * So simply ignore the ERROR_INVALID_HANDLE in that case to not
    844              * break other parts which rely on this function.
    845              */
    846             OSVERSIONINFOEX OSInfoEx = { 0 };
    847             OSInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
    848 
    849             bool fIgnoreError = false;
    850 
    851             /* Windows 7 or  earlier? */
    852             if (   GetVersionEx((LPOSVERSIONINFO) &OSInfoEx)
    853                 && (OSInfoEx.dwPlatformId == VER_PLATFORM_WIN32_NT)
    854                 && (OSInfoEx.dwMajorVersion <= 6)
    855                 && (OSInfoEx.dwMinorVersion <= 1))
     847            static PFNVERIFYCONSOLEIOHANDLE s_pfnVerifyConsoleIoHandle = NULL;
     848            static bool volatile            s_fInitialized = false;
     849            PFNVERIFYCONSOLEIOHANDLE        pfnVerifyConsoleIoHandle;
     850            if (fInitialized)
     851                pfnVerifyConsoleIoHandle = s_pfnVerifyConsoleIoHandle;
     852            else
    856853            {
    857                 PFNVERIFYCONSOLEIOHANDLE pfnVerifyConsoleIoHandle = NULL;
    858 
    859                 /*
    860                  * As the standard I/O handles could have been overwritten by SetStdHandle() we cannot assume
    861                  * that GetStdHandle will actually return real console I/O handles.
    862                  *
    863                  * So try to dynamically load the undocumented VerifyConsoleIoHandle from kernel32.dll.
    864                  * This function will check if the given handle actually is a console I/O handle, and if so,
    865                  * we know that we have to ignore the ERROR_INVALID_HANDLE on Windows 7 or earlier.
    866                  *
    867                  */
    868                 RTLDRMOD hKernel32 = NIL_RTLDRMOD;
    869                 int rc2 = RTLdrLoadSystem("kernel32.dll", true /*fNoUnload*/, &hKernel32);
    870                 if (RT_SUCCESS(rc2))
    871                     rc2 = RTLdrGetSymbol(hKernel32, "VerifyConsoleIoHandle", (void**)&pfnVerifyConsoleIoHandle);
    872 
    873                 if (RT_SUCCESS(rc2))
    874                 {
    875                     AssertPtr(pfnVerifyConsoleIoHandle);
    876 
    877                     /* Is the handle a console handle? Then ignore ERROR_INVALID_HANDLE. */
    878                     if (pfnVerifyConsoleIoHandle(hHandle))
    879                         fIgnoreError = true;
    880                 }
    881 
    882                 if (hKernel32 != NIL_RTLDRMOD)
    883                     RTLdrClose(hKernel32);
     854                int rc = RTLdrGetSystemSymbol(hKernel32, "VerifyConsoleIoHandle", (void **)&pfnVerifyConsoleIoHandle);
     855                if (RT_SUCCESS(rc))
     856                    s_pfnVerifyConsoleIoHandle = pfnVerifyConsoleIoHandle;
     857                else
     858                    pfnVerifyConsoleIoHandle = NULL;
     859                ASMAtomicWriteBool(&s_fInitialized, true);
    884860            }
    885 
    886             if (!fIgnoreError)
    887                 return RTErrConvertFromWin32(dwErr);
     861            if (   pfnVerifyConsoleIoHandle
     862                ? !pfnVerifyConsoleIoHandle(hHandle)
     863                : GetFileType(hHandle) == FILE_TYPE_UNKNOWN && GetLastError() != NO_ERROR)
     864                return VERR_INVALID_HANDLE;
    888865        }
     866        else
     867            return RTErrConvertFromWin32(dwErr);
     868
    889869        RT_ZERO(Data);
    890870        Data.dwFileAttributes = RTFS_DOS_NT_DEVICE;
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