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@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; }