msvcrt: dont overwrite the standard streams (with tests, try 7)

André Hentschel nerv at dawncrow.de
Tue Sep 8 13:38:25 CDT 2009


Some Apps e.g. mingw-apps use lpReserved2 to pass some data to the child-process, this data starts with 4 Byte of Zeros(unsinged 0) to tell msvcrt not to read that as an inherit-block.
See also Bug 18479

---
 dlls/msvcrt/file.c       |    2 +-
 dlls/msvcrt/tests/file.c |  166 +++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 166 insertions(+), 2 deletions(-)

diff --git a/dlls/msvcrt/file.c b/dlls/msvcrt/file.c
index 6671f2f..12ebd2c 100644
--- a/dlls/msvcrt/file.c
+++ b/dlls/msvcrt/file.c
@@ -349,7 +349,7 @@ void msvcrt_init_io(void)
   InitializeCriticalSection(&MSVCRT_file_cs);
   MSVCRT_file_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": MSVCRT_file_cs");
   GetStartupInfoA(&si);
-  if (si.cbReserved2 != 0 && si.lpReserved2 != NULL)
+  if (si.cbReserved2 >= sizeof(unsigned) && si.lpReserved2 != NULL && *(unsigned*)si.lpReserved2)
   {
     char*       wxflag_ptr;
     HANDLE*     handle_ptr;
diff --git a/dlls/msvcrt/tests/file.c b/dlls/msvcrt/tests/file.c
index d405656..bec49cb 100644
--- a/dlls/msvcrt/tests/file.c
+++ b/dlls/msvcrt/tests/file.c
@@ -857,12 +857,40 @@ static void test_file_inherit_child_no(const char* fd_s)
     ok( ret == -1 && errno == EBADF, 
        "Wrong write result in child process on %d (%s)\n", fd, strerror(errno));
 }
- 
+
+static void create_io_inherit_block( BYTE *block, HANDLE hstdout )
+{
+  char* wxflag_ptr;
+  HANDLE* handle_ptr;
+  WORD size;
+
+  size = sizeof(unsigned) + (sizeof(char) + sizeof(HANDLE)) * 3;
+  wxflag_ptr = (char*)block + sizeof(unsigned);
+  handle_ptr = (HANDLE*)(wxflag_ptr + 3 * sizeof(char));
+
+  *(unsigned*)block = 3;
+  *wxflag_ptr = 0x81;
+  *handle_ptr = GetStdHandle( STD_INPUT_HANDLE );
+  wxflag_ptr++; handle_ptr++;
+  *wxflag_ptr = 0x81;
+  *handle_ptr = hstdout;
+  wxflag_ptr++; handle_ptr++;
+  *wxflag_ptr = 0x81;
+  *handle_ptr = GetStdHandle( STD_ERROR_HANDLE );
+}
+
 static void test_file_inherit( const char* selfname )
 {
     int			fd;
     const char*		arg_v[5];
     char 		buffer[16];
+    char cmdline[MAX_PATH];
+    BYTE inheritblock[sizeof(unsigned) + 4 * (sizeof(char) + sizeof(HANDLE))];
+    STARTUPINFO startup;
+    SECURITY_ATTRIBUTES sa;
+    PROCESS_INFORMATION proc;
+    HANDLE hFile, hErrorFile;
+    DWORD ret;
 
     fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY, _S_IREAD |_S_IWRITE);
     ok(fd != -1, "Couldn't create test file\n");
@@ -890,6 +918,136 @@ static void test_file_inherit( const char* selfname )
     ok(read(fd, buffer, sizeof (buffer)) == 0, "Found unexpected data (%s)\n", buffer);
     close (fd);
     ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
+
+
+    /* make file handle inheritable */
+    sa.nLength = sizeof(sa);
+    sa.lpSecurityDescriptor = NULL;
+    sa.bInheritHandle = TRUE;
+    hErrorFile = CreateFileA( "fdopen.err", GENERIC_READ|GENERIC_WRITE,
+                              FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                              &sa, CREATE_ALWAYS, 0, NULL );
+    sprintf(cmdline, "%s file inherit_ow", selfname);
+
+    /* init an empty Reserved2, which should not be recognized as inherit-block */
+    ZeroMemory(&startup, sizeof(STARTUPINFO));
+    ZeroMemory(inheritblock, sizeof(inheritblock));
+    startup.cb = sizeof(startup);
+    startup.cbReserved2 = sizeof(inheritblock);
+    startup.lpReserved2 = inheritblock;
+
+    /* in case it fails pipe the stdout to a file */
+    startup.dwFlags    = STARTF_USESTDHANDLES;
+    startup.hStdInput  = GetStdHandle( STD_INPUT_HANDLE );
+    startup.hStdOutput = hErrorFile;
+    startup.hStdError  = GetStdHandle( STD_ERROR_HANDLE );
+
+    /* Test with empty inheritblock */
+    CreateProcessA(NULL, cmdline, NULL, NULL, TRUE,
+                   CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS, NULL, NULL, &startup, &proc);
+    winetest_wait_child_process( proc.hProcess );
+    buffer[0]=0;
+    SetFilePointer(hErrorFile, 0, NULL, FILE_BEGIN);
+    ReadFile(hErrorFile, buffer, 8, &ret, NULL);
+    CloseHandle(hErrorFile);
+    ok(strcmp(buffer, "Success") == 0 && ret==8, "Found unexpected data (%s)\n", buffer);
+    ok(unlink("fdopen.err") == 0, "Couldn't unlink\n");
+
+
+    /* init a fake inheritblock */
+    hFile = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
+                         FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                         &sa, CREATE_ALWAYS, 0, NULL );
+    create_io_inherit_block(inheritblock, hFile);
+    startup.dwFlags = 0;
+    startup.hStdInput = startup.hStdOutput = startup.hStdError = 0;
+
+    /* Test with fake inheritblock */
+    CreateProcessA(NULL, cmdline, NULL, NULL, TRUE,
+                   CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS, NULL, NULL, &startup, &proc);
+    winetest_wait_child_process( proc.hProcess );
+    buffer[0]=0;
+    SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
+    ReadFile(hFile, buffer, 8, &ret, NULL);
+    CloseHandle(hFile);
+    ok(strcmp(buffer, "Success") == 0 && ret==8, "Found unexpected data (%s)\n", buffer);
+    ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
+
+
+    /* init a fake inheritblock starting with unsigned zero */
+    hFile = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
+                         FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                         &sa, CREATE_ALWAYS, 0, NULL );
+    create_io_inherit_block(inheritblock, hFile);
+    *(unsigned*)inheritblock = 0;
+
+    /* in case it fails pipe the stdout to a file */
+    hErrorFile = CreateFileA( "fdopen.err", GENERIC_READ|GENERIC_WRITE,
+                              FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                              &sa, CREATE_ALWAYS, 0, NULL );
+    startup.dwFlags    = STARTF_USESTDHANDLES;
+    startup.hStdInput  = GetStdHandle( STD_INPUT_HANDLE );
+    startup.hStdOutput = hErrorFile;
+    startup.hStdError  = GetStdHandle( STD_ERROR_HANDLE );
+
+    /* Test with fake inheritblock starting with unsigned zero */
+    CreateProcessA(NULL, cmdline, NULL, NULL, TRUE,
+                   CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS, NULL, NULL, &startup, &proc);
+    winetest_wait_child_process( proc.hProcess );
+    buffer[0]=0;
+    SetFilePointer(hErrorFile, 0, NULL, FILE_BEGIN);
+    ReadFile(hErrorFile, buffer, 8, &ret, NULL);
+    CloseHandle(hErrorFile);
+    ok(strcmp(buffer, "Success") == 0 && ret==8, "Found unexpected data (%s)\n", buffer);
+    buffer[0]=0;
+    SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
+    ReadFile(hFile, buffer, 8, &ret, NULL);
+    CloseHandle(hFile);
+    ok(strcmp(buffer, "Success") != 0, "Found unexpected data (%s)\n", buffer);
+    ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
+    ok(unlink("fdopen.err") == 0, "Couldn't unlink\n");
+
+
+    /* init a fake inheritblock with smaller size */
+    hFile = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
+                         FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                         &sa, CREATE_ALWAYS, 0, NULL );
+    create_io_inherit_block(inheritblock, hFile);
+    startup.cbReserved2 = sizeof(inheritblock)-1;
+    startup.dwFlags = 0;
+    startup.hStdInput = startup.hStdOutput = startup.hStdError = 0;
+
+    /* Test with fake inheritblock with smaller size */
+    CreateProcessA(NULL, cmdline, NULL, NULL, TRUE,
+                   CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS, NULL, NULL, &startup, &proc);
+    winetest_wait_child_process( proc.hProcess );
+    buffer[0]=0;
+    SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
+    ReadFile(hFile, buffer, 8, &ret, NULL);
+    CloseHandle(hFile);
+    ok(strcmp(buffer, "Success") == 0 && ret==8, "Found unexpected data (%s)\n", buffer);
+    ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
+
+
+    /* init a fake inheritblock with larger size */
+    hFile = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
+                         FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                         &sa, CREATE_ALWAYS, 0, NULL );
+    create_io_inherit_block(inheritblock, hFile);
+    startup.cbReserved2 = sizeof(inheritblock)+1;
+    startup.dwFlags = 0;
+    startup.hStdInput = startup.hStdOutput = startup.hStdError = 0;
+
+    /* Test with fake inheritblock with larger size */
+    CreateProcessA(NULL, cmdline, NULL, NULL, TRUE,
+                   CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS, NULL, NULL, &startup, &proc);
+    winetest_wait_child_process( proc.hProcess );
+    buffer[0]=0;
+    SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
+    ReadFile(hFile, buffer, 8, &ret, NULL);
+    CloseHandle(hFile);
+    ok(strcmp(buffer, "Success") == 0 && ret==8, "Found unexpected data (%s)\n", buffer);
+    ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
 }
 
 static void test_tmpnam( void )
@@ -1223,6 +1381,12 @@ START_TEST(file)
             test_file_inherit_child(arg_v[3]);
         else if (strcmp(arg_v[2], "inherit_no") == 0)
             test_file_inherit_child_no(arg_v[3]);
+        else if (strcmp(arg_v[2], "inherit_ow") == 0)
+        {
+            char stdfd[2];
+            sprintf(stdfd, "%d", STDOUT_FILENO);
+            test_file_inherit_child(stdfd);
+        }
         else if (strcmp(arg_v[2], "pipes") == 0)
             test_pipes_child(arg_c, arg_v);
         else
-- 

Best Regards, André Hentschel



More information about the wine-patches mailing list