diff --git a/dlls/msvcrt/file.c b/dlls/msvcrt/file.c index b22cbeb4d6c..2516570db7e 100644 --- a/dlls/msvcrt/file.c +++ b/dlls/msvcrt/file.c @@ -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; } diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h index 1b117c83929..a380613077e 100644 --- a/dlls/msvcrt/msvcrt.h +++ b/dlls/msvcrt/msvcrt.h @@ -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 diff --git a/dlls/msvcrt/tests/Makefile.in b/dlls/msvcrt/tests/Makefile.in index 2db553d7aec..0867ac01ffe 100644 --- a/dlls/msvcrt/tests/Makefile.in +++ b/dlls/msvcrt/tests/Makefile.in @@ -1,6 +1,7 @@ TESTDLL = msvcrt.dll APPMODE = -mno-cygwin EXTRAINCL = -I$(srcdir)/.. +IMPORTS = advapi32 C_SRCS = \ cpp.c \ diff --git a/dlls/msvcrt/tests/file.c b/dlls/msvcrt/tests/file.c index d92a6e459a3..e0b94cf7f34 100644 --- a/dlls/msvcrt/tests/file.c +++ b/dlls/msvcrt/tests/file.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -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();