Piotr Caban : msvcrt: Return child exit code in _pclose function.

Alexandre Julliard julliard at winehq.org
Fri Jan 18 12:07:36 CST 2013


Module: wine
Branch: master
Commit: a968a1ad6dccd85548b62b43d7a0e41d2a4058d5
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=a968a1ad6dccd85548b62b43d7a0e41d2a4058d5

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Fri Jan 18 11:03:51 2013 +0100

msvcrt: Return child exit code in _pclose function.

Based on a patch by Borut Ražem.

---

 dlls/msvcrt/main.c    |    1 +
 dlls/msvcrt/msvcrt.h  |    1 +
 dlls/msvcrt/process.c |   72 +++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 72 insertions(+), 2 deletions(-)

diff --git a/dlls/msvcrt/main.c b/dlls/msvcrt/main.c
index ca761ad..6df9ccf 100644
--- a/dlls/msvcrt/main.c
+++ b/dlls/msvcrt/main.c
@@ -118,6 +118,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
   case DLL_THREAD_ATTACH:
     break;
   case DLL_PROCESS_DETACH:
+    msvcrt_free_popen_data();
     msvcrt_free_io();
     msvcrt_free_mt_locks();
     msvcrt_free_console();
diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h
index 4915309..ba67b65 100644
--- a/dlls/msvcrt/msvcrt.h
+++ b/dlls/msvcrt/msvcrt.h
@@ -269,6 +269,7 @@ extern void msvcrt_init_args(void) DECLSPEC_HIDDEN;
 extern void msvcrt_free_args(void) DECLSPEC_HIDDEN;
 extern void msvcrt_init_signals(void) DECLSPEC_HIDDEN;
 extern void msvcrt_free_signals(void) DECLSPEC_HIDDEN;
+extern void msvcrt_free_popen_data(void) DECLSPEC_HIDDEN;
 
 extern unsigned msvcrt_create_io_inherit_block(WORD*, BYTE**) DECLSPEC_HIDDEN;
 
diff --git a/dlls/msvcrt/process.c b/dlls/msvcrt/process.c
index d1e8e21..cc64c2d 100644
--- a/dlls/msvcrt/process.c
+++ b/dlls/msvcrt/process.c
@@ -31,6 +31,7 @@
 #include <stdarg.h>
 
 #include "msvcrt.h"
+#include "mtdll.h"
 #include "wine/debug.h"
 #include "wine/unicode.h"
 
@@ -1022,6 +1023,17 @@ MSVCRT_intptr_t CDECL _wspawnvp(int flags, const MSVCRT_wchar_t* name, const MSV
   return MSVCRT__wspawnvpe(flags, name, argv, NULL);
 }
 
+static struct popen_handle {
+    MSVCRT_FILE *f;
+    HANDLE proc;
+} *popen_handles;
+static DWORD popen_handles_size;
+
+void msvcrt_free_popen_data(void)
+{
+    MSVCRT_free(popen_handles);
+}
+
 /*********************************************************************
  *		_wpopen (MSVCRT.@)
  *
@@ -1036,6 +1048,8 @@ MSVCRT_FILE* CDECL MSVCRT__wpopen(const MSVCRT_wchar_t* command, const MSVCRT_wc
   MSVCRT_wchar_t *comspec, *fullcmd;
   unsigned int len;
   static const MSVCRT_wchar_t flag[] = {' ','/','c',' ',0};
+  struct popen_handle *container;
+  DWORD i;
 
   TRACE("(command=%s, mode=%s)\n", debugstr_w(command), debugstr_w(mode));
 
@@ -1069,6 +1083,25 @@ MSVCRT_FILE* CDECL MSVCRT__wpopen(const MSVCRT_wchar_t* command, const MSVCRT_wc
   fdToDup = readPipe ? 1 : 0;
   fdToOpen = readPipe ? 0 : 1;
 
+  _mlock(_POPEN_LOCK);
+  for(i=0; i<popen_handles_size; i++)
+  {
+    if (!popen_handles[i].f)
+      break;
+  }
+  if (i==popen_handles_size)
+  {
+    i = (popen_handles_size ? popen_handles_size*2 : 8);
+    container = MSVCRT_realloc(popen_handles, i*sizeof(*container));
+    if (!container) goto error;
+
+    popen_handles = container;
+    container = popen_handles+popen_handles_size;
+    memset(container, 0, (i-popen_handles_size)*sizeof(*container));
+    popen_handles_size = i;
+  }
+  else container = popen_handles+i;
+
   if ((fdStdHandle = MSVCRT__dup(fdToDup)) == -1)
     goto error;
   if (MSVCRT__dup2(fds[fdToDup], fdToDup) != 0)
@@ -1089,7 +1122,8 @@ MSVCRT_FILE* CDECL MSVCRT__wpopen(const MSVCRT_wchar_t* command, const MSVCRT_wc
   strcatW(fullcmd, flag);
   strcatW(fullcmd, command);
 
-  if (msvcrt_spawn(MSVCRT__P_NOWAIT, comspec, fullcmd, NULL, 1) == -1)
+  if ((container->proc = (HANDLE)msvcrt_spawn(MSVCRT__P_NOWAIT, comspec, fullcmd, NULL, 1))
+          == INVALID_HANDLE_VALUE)
   {
     MSVCRT__close(fds[fdToOpen]);
     ret = NULL;
@@ -1099,7 +1133,9 @@ MSVCRT_FILE* CDECL MSVCRT__wpopen(const MSVCRT_wchar_t* command, const MSVCRT_wc
     ret = MSVCRT__wfdopen(fds[fdToOpen], mode);
     if (!ret)
       MSVCRT__close(fds[fdToOpen]);
+    container->f = ret;
   }
+  _munlock(_POPEN_LOCK);
   HeapFree(GetProcessHeap(), 0, comspec);
   HeapFree(GetProcessHeap(), 0, fullcmd);
   MSVCRT__dup2(fdStdHandle, fdToDup);
@@ -1107,6 +1143,7 @@ MSVCRT_FILE* CDECL MSVCRT__wpopen(const MSVCRT_wchar_t* command, const MSVCRT_wc
   return ret;
 
 error:
+  _munlock(_POPEN_LOCK);
   if (fdStdHandle != -1) MSVCRT__close(fdStdHandle);
   MSVCRT__close(fds[0]);
   MSVCRT__close(fds[1]);
@@ -1145,7 +1182,38 @@ MSVCRT_FILE* CDECL MSVCRT__popen(const char* command, const char* mode)
  */
 int CDECL MSVCRT__pclose(MSVCRT_FILE* file)
 {
-  return MSVCRT_fclose(file);
+  HANDLE h;
+  DWORD i;
+
+  if (!MSVCRT_CHECK_PMT(file != NULL)) return -1;
+
+  _mlock(_POPEN_LOCK);
+  for(i=0; i<popen_handles_size; i++)
+  {
+    if (popen_handles[i].f == file)
+      break;
+  }
+  if(i == popen_handles_size)
+  {
+    _munlock(_POPEN_LOCK);
+    *MSVCRT__errno() = MSVCRT_EBADF;
+    return -1;
+  }
+
+  h = popen_handles[i].proc;
+  popen_handles[i].f = NULL;
+  _munlock(_POPEN_LOCK);
+
+  MSVCRT_fclose(file);
+  if(WaitForSingleObject(h, INFINITE)==WAIT_FAILED || !GetExitCodeProcess(h, &i))
+  {
+    msvcrt_set_errno(GetLastError());
+    CloseHandle(h);
+    return -1;
+  }
+
+  CloseHandle(h);
+  return i;
 }
 
 /*********************************************************************




More information about the wine-cvs mailing list