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