msvcrt-A12: _dup/_dup2 HANDLE duplication

Jaco Greeff jaco at puxedo.org
Mon Nov 4 09:16:31 CST 2002


This patch in the msvcrt-A?? series makes sure that we duplicate the 
associated HANDLE inside the _dup and _dup2 functions. This leads to the 
correct implementation and cleans up the hacked _close function 
considderably.

License:
LGPL

Changelog:
* dlls/msvcrt/file.c: Jaco Greeff <jaco at puxedo.org>
- Correctly duplicate the low-level file handle inside the _dup and 
_dup2 calls

--[ inline patch ]--

diff -aurN msvcrt-A11/dlls/msvcrt/file.c msvcrt-A12/dlls/msvcrt/file.c
--- msvcrt-A11/dlls/msvcrt/file.c	Mon Nov  4 15:06:39 2002
+++ msvcrt-A12/dlls/msvcrt/file.c	Mon Nov  4 17:11:35 2002
@@ -178,12 +178,9 @@
  }

  /* INTERNAL: duplicate an fd slot */
-static int msvcrt_dup_fd(int fd)
+static int msvcrt_dup_fd(int fd, int newfd)
  {
-    HANDLE hand = msvcrt_fdtoh(fd);
-    int newfd = MSVCRT_fdstart;
-
-    TRACE("(fd == %d), handle == %p\n", fd, hand);
+    HANDLE newhand, hand = msvcrt_fdtoh(fd);

      /* make sure we haven't exhausted our files
       * and that the original fd it does have a valid
@@ -204,7 +201,14 @@
       * to allow us to have access to the same file as
       * per the original fd
       */
-    MSVCRT_handles[newfd] = MSVCRT_handles[fd];
+    if (!DuplicateHandle(GetCurrentProcess(), hand,
+                         GetCurrentProcess(), &newhand,
+                         0, FALSE, DUPLICATE_SAME_ACCESS))
+    {
+        TRACE("Unable to duplicate source handle\n");
+        return -1;
+    }
+    MSVCRT_handles[newfd] = newhand;
      MSVCRT_flags[newfd] = MSVCRT_flags[fd];

      /* We don't have a specific MSVCRT_FILE or temp file
@@ -214,9 +218,7 @@
      MSVCRT_files[newfd] = NULL;
      MSVCRT_tempfiles[newfd] = NULL;

-    msvcrt_next_free(newfd);
-
-    return newfd;
+    return 0;
  }

  /* INTERNAL: Allocate a FILE* for an fd slot
@@ -442,7 +444,6 @@
   */
  int _close(int fd)
  {
-    int i, closed = 0;
      HANDLE hand = msvcrt_fdtoh(fd);

      TRACE("(fd == %d), handle == %p\n", fd, hand);
@@ -450,61 +451,47 @@
      if (hand == INVALID_HANDLE_VALUE)
          return -1;

-    /* The handle we are trying to close might have been
-     * _dup'ed, in which case we will need to clean all
-     * occurances of the specific handle in our internal
-     * tables. Hence we run through all and see if the
-     * handles match, if they do, we clean up
-     */
-    for (i = 0; i < MSVCRT_MAX_FILES; i++)
+    /* flush stdio buffers */
+    if (MSVCRT_files[fd])
      {
-        /* Ok, this is one occurace, clean it up */
-        if (MSVCRT_handles[i] == hand)
+        if (MSVCRT_files[fd]->_flag & MSVCRT__IOWRT)
+            MSVCRT_fflush(MSVCRT_files[fd]);
+        if (MSVCRT_files[fd]->_flag & MSVCRT__IOMYBUF)
          {
-            /* flush stdio buffers */
-            if (MSVCRT_files[i])
-            {
-                if (MSVCRT_files[i]->_flag & MSVCRT__IOWRT)
-                    MSVCRT_fflush(MSVCRT_files[i]);
-                if (MSVCRT_files[fd]->_flag & MSVCRT__IOMYBUF)
-                {
-                    MSVCRT_free(MSVCRT_files[i]->_base);
-                    MSVCRT_files[i]->_base = NULL;
-                }
-            }
-
-            /* Dont free std FILE*'s, they are not dynamic */
-            if (i > 2 && MSVCRT_files[i])
-            {
-                MSVCRT_free(MSVCRT_files[i]);
-                MSVCRT_files[i] = NULL;
-            }
-
-            msvcrt_free_fd(i);
-
-            /* If we haven't close the handle, do so once, and
-             * only once. This makes sure we don't close already
-             * closed occurances, which will fail
-             */
-            if ((!closed) && (!CloseHandle(hand)))
-            {
-                WARN(":failed-last error (%ld)\n" ,GetLastError());
-                MSVCRT__set_errno(GetLastError());
-                return -1;
-            }
-            MSVCRT_handles[i] = INVALID_HANDLE_VALUE;
-            closed = 1;
-
-            if (MSVCRT_tempfiles[i])
-            {
-                TRACE("deleting temporary file '%s'\n", 
MSVCRT_tempfiles[i]);
-                _unlink(MSVCRT_tempfiles[i]);
-                MSVCRT_free(MSVCRT_tempfiles[i]);
-                MSVCRT_tempfiles[i] = NULL;
-            }
+            MSVCRT_free(MSVCRT_files[fd]->_base);
+            MSVCRT_files[fd]->_base = NULL;
          }
      }

+    /* Dont free std FILE*'s, they are not dynamic */
+    if (fd > 2 && MSVCRT_files[fd])
+    {
+        MSVCRT_free(MSVCRT_files[fd]);
+        MSVCRT_files[fd] = NULL;
+    }
+
+    msvcrt_free_fd(fd);
+
+    /* If we haven't close the handle, do so once, and
+    * only once. This makes sure we don't close already
+    * closed occurances, which will fail
+    */
+    if (!CloseHandle(hand))
+    {
+        WARN(":failed-last error (%ld)\n" ,GetLastError());
+        MSVCRT__set_errno(GetLastError());
+        return -1;
+    }
+    MSVCRT_handles[fd] = INVALID_HANDLE_VALUE;
+
+    if (MSVCRT_tempfiles[fd])
+    {
+        TRACE("deleting temporary file '%s'\n", MSVCRT_tempfiles[fd]);
+        _unlink(MSVCRT_tempfiles[fd]);
+        MSVCRT_free(MSVCRT_tempfiles[fd]);
+        MSVCRT_tempfiles[fd] = NULL;
+    }
+
      TRACE(":ok\n");
      return 0;
  }
@@ -713,8 +700,15 @@
   */
  int _dup(int fd)
  {
+    int newfd = MSVCRT_fdstart;
+
      TRACE("(fd == %d)\n", fd);
-    return msvcrt_dup_fd(fd);
+
+    if (msvcrt_dup_fd(fd, newfd) == -1)
+        return -1;
+    msvcrt_next_free(newfd);
+
+    return newfd;
  }

  /*********************************************************************
@@ -722,44 +716,21 @@
   */
  int _dup2(int fd1, int fd2)
  {
-    HANDLE hand = msvcrt_fdtoh(fd1);
-
      TRACE("(fd1 == %d, fd2 == %d)\n", fd1, fd2);

-    /* Make sure that the handle for fd1 is valid and
-     * that fd2 is a valid file descriptor
-     */
-    if (hand == INVALID_HANDLE_VALUE)
-    {
-        TRACE("Invalid fd == %d, no associated handle\n", fd1);
-        return -1;
-    }
-    else if ((fd2 < 0) || (fd2 >= MSVCRT_fdend))
-    {
-        TRACE("Invalid fd == %d\n", fd2);
-        return -1;
-    }
-
      /* Close the file associated with fd2, before
-     * assigning it another value from fd1
+     * assigning duplicating it with values from fd1
       */
      _close(fd2);
-
-    /* Duplicate the file handle and flags for fd2,
-     * to allow us to have access to the same file as
-     * per the original fd1
-     */
-    MSVCRT_handles[fd2] = MSVCRT_handles[fd1];
-    MSVCRT_flags[fd2] = MSVCRT_flags[fd1];
-    MSVCRT_files[fd2] = NULL;
-    MSVCRT_tempfiles[fd2] = NULL;
+    if (msvcrt_dup_fd(fd1, fd2) == -1)
+        return -1;

      /* If fd2 was marked as the first free file descriptor,
       * re-allocate it as not to be used
       */
      if (fd2 == MSVCRT_fdstart)
          msvcrt_next_free(fd2);
-
+
      return 0;
  }





More information about the wine-patches mailing list