msvcrt: Fix IO initialization when invalid handles are passed.

Signed-off-by: Piotr Caban <piotr@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Piotr Caban 2017-11-15 09:47:23 +01:00 committed by Alexandre Julliard
parent 206162365d
commit 31bf13e92b
4 changed files with 98 additions and 7 deletions

View File

@ -581,30 +581,57 @@ void msvcrt_init_io(void)
fdinfo = get_ioinfo_alloc_fd(MSVCRT_STDIN_FILENO);
if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE) {
HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
DWORD flags = WX_OPEN | WX_TEXT;
DWORD type = GetFileType(h);
msvcrt_set_fd(fdinfo, h, WX_OPEN|WX_TEXT|((type&0xf)==FILE_TYPE_CHAR ? WX_TTY : 0)
|((type&0xf)==FILE_TYPE_PIPE ? WX_PIPE : 0));
if (type == FILE_TYPE_UNKNOWN) {
h = MSVCRT_NO_CONSOLE;
flags |= WX_TTY;
} else if ((type & 0xf) == FILE_TYPE_CHAR) {
flags |= WX_TTY;
} else if ((type & 0xf) == FILE_TYPE_PIPE) {
flags |= WX_PIPE;
}
msvcrt_set_fd(fdinfo, h, flags);
}
release_ioinfo(fdinfo);
fdinfo = get_ioinfo_alloc_fd(MSVCRT_STDOUT_FILENO);
if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE) {
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD flags = WX_OPEN | WX_TEXT;
DWORD type = GetFileType(h);
msvcrt_set_fd(fdinfo, h, WX_OPEN|WX_TEXT|((type&0xf)==FILE_TYPE_CHAR ? WX_TTY : 0)
|((type&0xf)==FILE_TYPE_PIPE ? WX_PIPE : 0));
if (type == FILE_TYPE_UNKNOWN) {
h = MSVCRT_NO_CONSOLE;
flags |= WX_TTY;
} else if ((type & 0xf) == FILE_TYPE_CHAR) {
flags |= WX_TTY;
} else if ((type & 0xf) == FILE_TYPE_PIPE) {
flags |= WX_PIPE;
}
msvcrt_set_fd(fdinfo, h, flags);
}
release_ioinfo(fdinfo);
fdinfo = get_ioinfo_alloc_fd(MSVCRT_STDERR_FILENO);
if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE) {
HANDLE h = GetStdHandle(STD_ERROR_HANDLE);
DWORD flags = WX_OPEN | WX_TEXT;
DWORD type = GetFileType(h);
msvcrt_set_fd(fdinfo, h, WX_OPEN|WX_TEXT|((type&0xf)==FILE_TYPE_CHAR ? WX_TTY : 0)
|((type&0xf)==FILE_TYPE_PIPE ? WX_PIPE : 0));
if (type == FILE_TYPE_UNKNOWN) {
h = MSVCRT_NO_CONSOLE;
flags |= WX_TTY;
} else if ((type & 0xf) == FILE_TYPE_CHAR) {
flags |= WX_TTY;
} else if ((type & 0xf) == FILE_TYPE_PIPE) {
flags |= WX_PIPE;
}
msvcrt_set_fd(fdinfo, h, flags);
}
release_ioinfo(fdinfo);
@ -616,7 +643,8 @@ void msvcrt_init_io(void)
for (i = 0; i < 3; i++)
{
/* FILE structs for stdin/out/err are static and never deleted */
MSVCRT__iob[i]._file = i;
MSVCRT__iob[i]._file = get_ioinfo_nolock(i)->handle == MSVCRT_NO_CONSOLE ?
MSVCRT_NO_CONSOLE_FD : i;
MSVCRT__iob[i]._tmpfname = NULL;
MSVCRT__iob[i]._flag = (i == 0) ? MSVCRT__IOREAD : MSVCRT__IOWRT;
}

View File

@ -742,6 +742,9 @@ struct MSVCRT__stat64 {
#define MSVCRT_SEEK_CUR 1
#define MSVCRT_SEEK_END 2
#define MSVCRT_NO_CONSOLE_FD (-2)
#define MSVCRT_NO_CONSOLE ((HANDLE)MSVCRT_NO_CONSOLE_FD)
#define MSVCRT_STDIN_FILENO 0
#define MSVCRT_STDOUT_FILENO 1
#define MSVCRT_STDERR_FILENO 2

View File

@ -1,6 +1,7 @@
TESTDLL = msvcrt.dll
APPMODE = -mno-cygwin
EXTRAINCL = -I$(srcdir)/..
IMPORTS = advapi32
C_SRCS = \
cpp.c \

View File

@ -31,6 +31,7 @@
#include <windef.h>
#include <winbase.h>
#include <winnls.h>
#include <winreg.h>
#include <process.h>
#include <errno.h>
#include <locale.h>
@ -1522,6 +1523,61 @@ static void test_file_inherit( const char* selfname )
DeleteFileA("fdopen.tst");
}
static void test_invalid_stdin_child( void )
{
HANDLE handle;
ioinfo *info;
errno = 0xdeadbeef;
handle = (HANDLE)_get_osfhandle(STDIN_FILENO);
ok(handle == (HANDLE)-2, "handle = %p\n", handle);
ok(errno == 0xdeadbeef, "errno = %d\n", errno);
info = &__pioinfo[STDIN_FILENO/MSVCRT_FD_BLOCK_SIZE][STDIN_FILENO%MSVCRT_FD_BLOCK_SIZE];
ok(info->handle == (HANDLE)-2, "info->handle = %p\n", info->handle);
ok(info->wxflag == 0xc1, "info->wxflag = %x\n", info->wxflag);
ok(stdin->_file == -2, "stdin->_file = %d\n", stdin->_file);
}
static void test_invalid_stdin( const char* selfname )
{
char cmdline[MAX_PATH];
PROCESS_INFORMATION proc;
SECURITY_ATTRIBUTES sa;
STARTUPINFOA startup;
HKEY key;
LONG ret;
if(!p_fopen_s) {
/* Behaviour of the dll has changed in newer version */
win_skip("skipping invalid stdin tests\n");
return;
}
ret = RegOpenCurrentUser(KEY_READ, &key);
ok(!ret, "RegOpenCurrentUser failed: %x\n", ret);
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
memset(&startup, 0, sizeof(startup));
startup.cb = sizeof(startup);
startup.dwFlags = STARTF_USESTDHANDLES;
startup.hStdInput = key;
startup.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
startup.hStdError = GetStdHandle(STD_ERROR_HANDLE);
sprintf(cmdline, "%s file stdin", selfname);
CreateProcessA(NULL, cmdline, NULL, NULL, TRUE,
CREATE_DEFAULT_ERROR_MODE|NORMAL_PRIORITY_CLASS, NULL, NULL, &startup, &proc);
winetest_wait_child_process(proc.hProcess);
ret = RegCloseKey(key);
ok(!ret, "RegCloseKey failed: %x\n", ret);
}
static void test_tmpnam( void )
{
char name[MAX_PATH] = "abc";
@ -2461,12 +2517,15 @@ START_TEST(file)
test_file_inherit_child_no(arg_v[3]);
else if (strcmp(arg_v[2], "pipes") == 0)
test_pipes_child(arg_c, arg_v);
else if (strcmp(arg_v[2], "stdin") == 0)
test_invalid_stdin_child();
else
ok(0, "invalid argument '%s'\n", arg_v[2]);
return;
}
test_dup2();
test_file_inherit(arg_v[0]);
test_invalid_stdin(arg_v[0]);
test_file_write_read();
test_chsize();
test_stat();